locked
JavaScript Decimal Math RRS feed

  • Question

  • User657329123 posted

    Hello,

    When I do 34.09 * 11, I get 374.99 but if I add 340.91 and 34.09 in JavaScript, I get 375.00 instead of 374.99.  Here is my code:

    <p id="demo"></p>
    var num = (parseFloat(340.90) + parseFloat(34.09));
    num = parseFloat(num).toFixed(2);
    document.getElementById("demo").innerHTML = n;
    

    Why JavaScript is rounding 374.99 to 375. What do I need to do to get 374.99?

    Joe

    Thursday, March 4, 2021 5:10 PM

Answers

  • User-474980206 posted

    javascript does not do decimal arithmetic. all numbers are 64 bit floats. floats (because they are binary rather than decimal) can not be used for money, as you will get precision errors. this is usually covered in comp sci 101, so I assume you don't have a formal edition in computer science.

    just like 1/3 is .33333.. in decimal, several decimal number are repeating binaries.   see:

      https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

    the typical solution to calculating money with floats is to use a fixed precision library (like C# money) or do all the calculations in pennies (or mills if more precision required) and divide by 100 (or 1000 if mills) 

      > (3409 + 3409 + 3409 + 3409 + 3409) / 100 
      < 170.45

    you can do a simple javascript math package:

    const pennyMath = { 
        toPenny: (d) => Math.round(d * 100), 
        add: (d1,d2) => (pennyMath.toPenny(d1) + pennyMath.toPenny(d2)) / 100, 
        sub: (d1,d2) => (pennyMath.toPenny(d1) - pennyMath.toPenny(d2)) / 100, 
        mul: (d1,d2) => Math.round(pennyMath.toPenny(d1) * pennyMath.toPenny(d2)) / 100, 
        div: (d1,d2) => Math.round(pennyMath.toPenny(d1) / pennyMath.toPenny(d2)) / 100, 
        sum: (...d) => d.reduce((a,c) => pennyMath.toPenny(c) + a,0) / 100
    };

    then:

      pennyMath.sum(34.09 , 34.09 , 34.09 , 34.09 , 34.09)

    gives 170.45



          

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 4, 2021 9:22 PM
  • User303363814 posted

    toFixed rounds to the number of decimal places requested. 170.455 when rounded to two decimal places id 170.46.

    One way to truncate to two decimal places would be to multiply by 100, take the .floor (which finds the largest integer smaller than or equal to the argument) and then divide by 100. (If you want three decimal places then use 1,000 instead of 100, etc)

    const truncated = (Math.floor(myNum * 100) / 100).toString();

    (What do you want to do with negative numbers?  The above will display -4.567 as -4.57)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 4, 2021 10:28 PM

All replies

  • User475983607 posted

    joegreen2005

    Hello,

    When I do 34.09 * 11, I get 374.99 but if I add 340.91 and 34.09 in JavaScript, I get 375.00 instead of 374.99.  Here is my code:

    <p id="demo"></p>
    var num = (parseFloat(340.91) + parseFloat(34.09));
    num = parseFloat(num).toFixed(2);
    document.getElementById("demo").innerHTML = n;

    Why JavaScript is rounding 374.99 to 375. What do I need to do to get 374.99?

    Joe

    Your math is wrong.  

    340.91 + 34.09  = 375

    Maybe you mean

    340.91 + 34.08 = 374.99

    Plus your code has a bug.

    Thursday, March 4, 2021 6:42 PM
  • User657329123 posted

    The error is happening when I add 34.09 + 34.09 + 34.09 + 34.09 + 34.09,  I get 170.455 and when I do 170.455.toFixed(2) I get 170.46 which should be 170.45 and not 170.46.

    Thursday, March 4, 2021 7:27 PM
  • User-474980206 posted

    javascript does not do decimal arithmetic. all numbers are 64 bit floats. floats (because they are binary rather than decimal) can not be used for money, as you will get precision errors. this is usually covered in comp sci 101, so I assume you don't have a formal edition in computer science.

    just like 1/3 is .33333.. in decimal, several decimal number are repeating binaries.   see:

      https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

    the typical solution to calculating money with floats is to use a fixed precision library (like C# money) or do all the calculations in pennies (or mills if more precision required) and divide by 100 (or 1000 if mills) 

      > (3409 + 3409 + 3409 + 3409 + 3409) / 100 
      < 170.45

    you can do a simple javascript math package:

    const pennyMath = { 
        toPenny: (d) => Math.round(d * 100), 
        add: (d1,d2) => (pennyMath.toPenny(d1) + pennyMath.toPenny(d2)) / 100, 
        sub: (d1,d2) => (pennyMath.toPenny(d1) - pennyMath.toPenny(d2)) / 100, 
        mul: (d1,d2) => Math.round(pennyMath.toPenny(d1) * pennyMath.toPenny(d2)) / 100, 
        div: (d1,d2) => Math.round(pennyMath.toPenny(d1) / pennyMath.toPenny(d2)) / 100, 
        sum: (...d) => d.reduce((a,c) => pennyMath.toPenny(c) + a,0) / 100
    };

    then:

      pennyMath.sum(34.09 , 34.09 , 34.09 , 34.09 , 34.09)

    gives 170.45



          

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 4, 2021 9:22 PM
  • User303363814 posted

    toFixed rounds to the number of decimal places requested. 170.455 when rounded to two decimal places id 170.46.

    One way to truncate to two decimal places would be to multiply by 100, take the .floor (which finds the largest integer smaller than or equal to the argument) and then divide by 100. (If you want three decimal places then use 1,000 instead of 100, etc)

    const truncated = (Math.floor(myNum * 100) / 100).toString();

    (What do you want to do with negative numbers?  The above will display -4.567 as -4.57)

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 4, 2021 10:28 PM