Javascript multiplying incorrectly, causing incorrect rounding

When I pull the values I want to multiply, they're strings. So I pull them, parse them as floats (to preserve the decimal places), and multiply them together.

LineTaxRate = parseFloat(myRate) * parseFloat(myQuantity) * parseFloat(myTaxRateRound);

This has worked for 99% of my invoices but I discovered one very odd problem.

When it multiplied: 78 * 7 * 0.0725

Javascript is returning: 39.584999999999994

When you normally do the math in a calculator its: 39.585

When all is said and done, I take that number and round it using .toFixed(2)

Because Javascript is returning that number, it's not rounding to the desired value of: $39.59

I tried Math.round() the total but I still get the same number.

I have thought of rounding the number to 3 decimals then two, but that seems hacky to me.

I have searched everywhere and all I see is people mention parseFloat loses its precision, and to use .toFixed, however in the example above, that doesn't help.

Here is my test script i made to recreate the issue:

<script>
var num1 = parseFloat("78");
var num2 = parseFloat("7");
var num3 = parseFloat("0.0725");
var myTotal = num1 * num2 * num3;
var result = Math.round(myTotal*100)/100

alert(myTotal);
alert(myTotal.toFixed(2));
alert(result);
</script>

Answers:

Answer

Floating points are represented in binary, not decimal. Some decimal numbers will not be represented precisely. And unfortunately, since Javascript only has one Number class, it's not a very good tool for this job. Other languages have decent decimal libraries designed to avoid precisely this kind of error. You're going to have to either accept one-cent errors, implement a solution server-side, or work very hard to fix this.

edit: ooh! you can do 78 * 7 * 725 and then divide by 10000, or to be even more precise just put the decimal point in the right place. Basically represent the tax rate as something other than a tiny fraction. Less convenient but it'll probably take care of your multiplication errors.

Answer

You might find the Accounting.js library useful for this. It has an "improved" toFixed() method.

Answer

JavaScript/TypeScript have only one Number class which is not that good. I have the same problem as I am using TypeScript. I solved my problem by using decimal.js-light library.

new Decimal(78).mul(7).mul(0.0725) returns as expected 39.585

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.