1

I am building an app in Angular and I'm trying to find the most accurate way to perform simple mathematical equations. As a simple example, take the sum

0.1 + 0.2

As most of us know, this doesn't simply return 0.3, instead it returns

0.30000000000000004

However, in my app I require the results of these equations to be very accurate, i.e. I need 0.3 as the result. A common way to fix this is by using the toFixed function:

(0.1 + 0.2).toFixed(2) = 0.30

However, this will not solve my issue. Let's say I need to divide 1 by 11, but in this case I actually need all decimal values:

1/11 = 0.09090909090909091

Whereas toFixed(2) would actually return only 0.09, but for my application I need higher precision, i.e. the result above.

Is there a way to perform these simple equations while still getting accurate results? i.e. 0.1 + 0.2 = 0.3 and 1/11 = 0.09090909090909091.

EDIT

Here is another example:

15.7 + 17.4 + 17.39 = 50.48999999999999

whereas the answer should be 50.49

vdvaxel
  • 137
  • 1
  • 2
  • 11
  • Floating-point math in JavaScript is based on a *binary* floating-point standard, as is common in many programming languages. – Pointy Apr 19 '20 at 16:55
  • Typically, esp. with JavaScript (and for production) it is best to use a library already set-up to handle these issues. BigNumber is an example of this — https://github.com/MikeMcl/bignumber.js — although there may be more lightweight solutions. – Pebbl Apr 19 '20 at 17:15

2 Answers2

0

If you're doing addition, you could try multiplying everything by a multiple of 10 and dividing by it. For example, instead of 0.1 + 0.2, do (0.1 * 100 + 0.2 * 100) / 100. That makes 30, which you can then divide by 100.
For division, you could try thinking about how a human would do division. For 1 / 11, that's saying how many times does 11 fit into one. None, so you go smaller. How many times does 1.1 fit into 1? None, so you go smaller. How many times does 0.11 fit into 1? At this point, you use the previous trick. 11 fits into 100, so we go bigger. 11 * 2 fits into 100, so we go bigger. You can keep going until you realize that 11 * 10 doesn't fit into 100. You can keep doing this until you reach your level of precision. Sure, it's hacky and slow, but it works. You can even do fine-level math, past the 16-digit imprecision level.
For why this happens, look at this answer: https://stackoverflow.com/a/27030789/12243248

KTibow
  • 495
  • 6
  • 18
0

You can use toPrecision() method which returns a string representing your number, passing a parameter specifying the number of significant digits (16 if you want to crop the result) and then parse it into a Number.

For your examples:

Number(parseFloat(0.1 + 0.2).toPrecision(16)) = 0.3

Number(parseFloat(1/11).toPrecision(16)) = 0.09090909090909091
Juan Diego Lozano
  • 989
  • 2
  • 18
  • 30
  • Thanks for your answer, however I still have an issue in some cases. Take this example: `15.7 + 17.4 + 17.39 = 50.48999999999999` whereas the answer should just be `50.49` – vdvaxel Apr 19 '20 at 18:02