5

While working on measurement.js, the joys of TDD helped me stumble upon a really strange (at least as i occurs to me) behaviour exposed in the javascript engines.

No matter if entered into the console or performed inside a script, this is what happens:

-1 + 0.85     --> -0.85               ✓  
-1 + 1        --> 0                   ✓   
-1 + 1 + -.15 --> 0.15                ✓
-1 + 1.15     --> 0.1499999999999999  ?!?

This is tested and reproduced exactly under following Browsers / OS's:

  • FF 24.0 (Debian 3.10)
  • Chrome 30.0.1599.114 (Debian 3.10)
  • Chrome 30.0.1599.101m (Win7SP1)
  • Internet Explorer 10.0.9200.16721 (Win7SP1)

As this is consistent throughout different vendors, i assume there must be a specific reason for this, so:

  • What is the reason for this?
  • What is the best practice to circumvent this behaviour, as it poses a problem for exact calculations with JS

Update:
Best lay-comprehensible explanation incl. answers and workarounds for multiple programming languages so far found at
http://floating-point-gui.de/ (thanx @RocketHazmat)

Philzen
  • 3,945
  • 30
  • 46

2 Answers2

0

No duh. You try doing the math in base two.

Short answer: you can't do it. It's like trying to add 1/3 in decimal repeatedly. You get 0.333333, then 0.666666, then 0.99999... but shouldn't that last one be 3/3, in other words 1?

To avoid this problem, just use integers for everything, as much as possible.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • +1, but `just use integers for everything, as much as possible` - was that a joke? Isn't the solution to use toFixed before presenting the results to the client? – Adam Rackis Oct 24 '13 at 19:06
  • 1
    "No duh. you try doing the math" - unhelpul, now i feel more stupid than before. "just use integers for everything" - so what you'd suggest as an integer representation of 1.15 ? – Philzen Oct 24 '13 at 19:07
  • 1
    @AdamRackis: That wasn't a joke. With money for example, do the math in "cents". Instead of doing `0.1+0.2`, do `10+20`, then convert to dollars later. `(10+20)/100 => 0.3` – gen_Eric Oct 24 '13 at 19:07
  • 2
    @Philzen: Times it by 100, do the math, then divide by 100. `(-100 + 115)/100 => 1.5`. Or use `toFixed`: `(-1 + 1.15).toFixed(2)`. – gen_Eric Oct 24 '13 at 19:11
  • @RocketHazmat - thx, that's heaps better and actually answers half of my question. I'll try to read through the referenced links and see if i can grasp why this isn't done internally anyway (i mean any cheap desktop calculator gets this addition right, shouldn't JS do it as well?) – Philzen Oct 24 '13 at 19:15
  • 2
    @Philzen: Check out this page: http://floating-point-gui.de/ It should explain it. – gen_Eric Oct 24 '13 at 19:16
0

I think this is because of the problems inherent in representing some floating point numbers in binary.

Read this:- What Every Computer Scientist Should Know About Floating-Point Arithmetic.

Try to use toFixed to avoid your problem

Formats a number using fixed-point notation.

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331