-1

Possible Duplicate:
Is JavaScript’s Floating-Point Math Broken?

I have a strange mathematical problem during a multiplication in javascript.

$(parent).find('#id_deals-' + i + '-quantity').val()

result -> 10

$(parent).find('#id_deals-' + i + '-price').val()

result -> 3.99

Both above mulltiplied like this:

$(parent).find('#id_deals-' + i + '-price').val() * $(parent).find('#id_deals-' + i + '-quantity').val()

result --> 39.900000000000006

Why is this happening? and what can I do to limit the decimal places to 2 digits only?

Is it maybe because 10 has to be 10.0 ? But how do I convert my value to this format automatically before the actual multiplication?

Update: According to syazdani's answer, I have tried to implement bigdecimal as suggested:

It is not well documented, but I got it working like this:

function run(opts) {
    var bd = {"BigDecimal":BigDecimal, "BigInteger":BigInteger, "RoundingMode":RoundingMode};
    var result;
    var ops = {'*': "multiply", '/': "divide", '+': "add", '-': "subtract"};
    var a = new bd.BigDecimal("" + opts.a);
    var b = new bd.BigDecimal("" + opts.b);
    var op = ops[opts.op];
    if (op == "divide") {
        return a.divide(b, 300, bd.RoundingMode.HALF_UP());
    } else {
        return a[op].call(a, b);
    }
}


function multiply(a, b){
    return run({"a":a,"b":b,"op":"*"}); 
} 
Community
  • 1
  • 1
Houman
  • 64,245
  • 87
  • 278
  • 460
  • 2
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Dave Newton Jan 22 '13 at 17:43
  • yeah true, the first link indicates the same problem and it might look like a duplicate , however the accepted answer there doesn't help me e at all. The answer below with `.toFixed(2)` nails it though. :) thanks – Houman Jan 22 '13 at 17:44
  • Note that `toFixed` is just a formatting function that returns a string. The accepted answer on my proposed dupe links to the same article Dave Newton suggested, and which contains an in-depth explanation for why floating-point math behaves like that. – bfavaretto Jan 22 '13 at 17:55

3 Answers3

2

If you are working with currency (as it seems that you are given the "price" id), you may be better served by using a so called Big Number library (such as this one: https://github.com/iriscouch/bigdecimal.js) for your math to control the math (round up vs round down, etc.). It takes a bit more work to get everything right, but it is worthwhile to avoid the Office Space math scenario.

syazdani
  • 4,760
  • 1
  • 26
  • 35
  • Interesting point. Thanks. I just found another solution, how about rounding it instead of `.ToFixed(2)` like this: `(Math.round(total_value*100)/100)` ? Would that be reliable or would you still recommend bigdecimals? – Houman Jan 22 '13 at 17:49
  • Yup. as a refinement of your comment, you could treat and compute the value as always being in Cents (or some constant fraction of a cent if higher precision is necessary), and only *display* the value as Dollars and Cents when necessary. So internally, the number is always an integer (no pesky floats). You would only have to worry about division in that case. We chose to use BigDecimal because we had to deal with arbitrary fractions of cents so could not fix the number of digits we stored internally. Depends on your use case I suppose. – syazdani Jan 22 '13 at 18:14
  • Thanks for the explanation. I am have downloaded the bigdecimal.js 0.6.1 and can see its loaded in my app (firebug). But the moment I do: `var bigdecimal = require("bigdecimal");` it crashes. No error given on console. Have you come across that before? – Houman Jan 22 '13 at 18:17
  • I do not know, but the version of BigDecimal that I am using didn't need requirejs: https://github.com/jhs/bigdecimal.js/blob/master/lib/bigdecimal.js. We just included it in a script tag and off we went. – syazdani Jan 22 '13 at 18:37
  • +1 I finally found out how it works. I updated the question. Thanks a lot for the suggestion. It works nicely. :) – Houman Jan 23 '13 at 08:59
1

All javascript number are IEEE-754 double precision floating points numbers. That means that they suffer from round-off errors and imprecision.

George
  • 4,147
  • 24
  • 33
0

All numbers in javascript are floating point numbers, based on IEEE754.

If you want to format one as a string with a fixed number of digits after the dot, use

var formattedNumber = v.toFixed(2); // this makes a string
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758