1

I know that certain numbers will get slight variations from their original value.

  • Eg. 0.1 + 0.2 -> 0.30000000000000004.

But if I do Math.round(0.30000000000000004 * 100) / 100, I will get the correct answer -> 0.3.

I ran a Javascript test and found that the results will accurate at least up to 1e+10.

Are there any caveats to doing this?

If I use Math.round(result * 100) / 100 after every calculation, can I be sure the results will be accurate?

The only calculations I plan to make are addition and multiplication and all numbers will only have 2 decimal places as confirmed by Math.round(n * 100) / 100.

I don't need the numbers to be accurate over about $1000.

Can I be sure my results will be accurate to the nearest cent?

trinalbadger587
  • 1,905
  • 1
  • 18
  • 36
  • 5
    If this is money, it would be better to represent them as integer cents, rather than fractions. – Barmar Jun 30 '21 at 22:04
  • I'd say you'd be fine if it's not for actual money handling. Otherwise [this article](https://frontstuff.io/how-to-handle-monetary-values-in-javascript) seems to recommend Dinero.js and that is something I have seen recommended in the past for handling real monetary values in JavaScript. – Johan Jarvi Jun 30 '21 at 22:05
  • 2
    When you're displaying to the user, divide by 100 and use `toFixed()` to show 2 decimal places. – Barmar Jun 30 '21 at 22:05
  • 1
    It is possible for a chain of additions and multiplications to grow an error to be infinitely large. – Eric Postpischil Jun 30 '21 at 23:09
  • What about just for adding not multiplication? – trinalbadger587 Jun 30 '21 at 23:27
  • 1
    Describe the calculations in more detail. Are any of the numbers negative? What multiplications are being done? Multiplications by interest rates or discount percentages? Or just integers? Small integers? How big can the input numbers be? How big can the output numbers be? How many additions and multiplications can there be? Describe what this is for so we can characterize the arithmetic. – Eric Postpischil Jul 01 '21 at 11:17
  • I'd suggest leaving any rounding until as late as possible, i.e. just before presenting values to the user, and probably using `toFixed()`. if you need to use the value in another calculation, then parse the formatted string back to a float. the reasons are that rounding can cause small errors to grow large quickly, and users might check your calculations so you want to make sure you're using the values you're showing them – Sam Mason Jul 01 '21 at 11:55
  • @EricPostpischil, adding positive numbers with 2 decimal places with a total of less than $1000. – trinalbadger587 Jul 01 '21 at 16:52
  • 1
    The total accumulated rounding error in adding up to 100,000 numbers that have a total less than 1,000 is less than 5.7e-9. If all of the numbers originated as multiples of .01 before conversion to JavaScripts `Number` format, then the computed total will be so near the desired total that rounding the computed total to a multiple of .01 will produce the correct total of the original numbers. (This error bound is because the error in an addition that produces a sum of magnitude less than 1000 is at most 512•2^−53, and 100,000 such errors is 10^5•2^9•2^−53 < 5.7e−9.) – Eric Postpischil Jul 01 '21 at 17:00

1 Answers1

1

You may face some errors while using Math.round(n * 100) / 100 . It won't always give your expected result, as for example:

console.log(Math.round(0.145*100)/100)

the expected result would be 0.15. it happens because there are some floats like 0.145 * 100 = 14.499999999999998

i suggest using different approaches, such as:

expected-round

Number.EPSILON

more on that topic:

How to round to at most 2 decimal places, if necessary?

How to format a float in javascript?

Sam
  • 723
  • 5
  • 18
  • 1
    note that this is because `0.145` can't be represented accurately by a float. the nearest float is good to ~18 decimal places, but is slightly smaller than the decimal value. because it's just the below boundary, rounding causes a complete loss of precision and you're left with only a single correct digit. hence my suggestion, above, of leaving all rounding as late as possible – Sam Mason Jul 01 '21 at 12:07