3

I was trying simple subtraction of float values and I got a weird output of negative zero:

var pay = -0.33;
var res = parseFloat(pay) + parseFloat(0.11) + parseFloat(0.22);
res = res.toFixed(2);
console.log(res);

output: -0.00

user3483203
  • 50,081
  • 9
  • 65
  • 94
sar
  • 1,277
  • 3
  • 21
  • 48
  • 5
    What's weird about it? The actual number is `-2.7755575615628914e-17`. It's that small that when you convert it to string via `toFixed(2)` that the result is `0.00`. The sign shows that it has been rounded up from a negative number. – Rory McCrossan Oct 08 '15 at 10:29
  • there are already multiple js parsing float values questions: http://stackoverflow.com/questions/1458633/how-to-deal-with-floating-point-number-precision-in-javascript http://stackoverflow.com/questions/11695618/dealing-with-float-precision-in-javascript – BHoft Oct 08 '15 at 10:30

4 Answers4

3

Nothing strange here, this is how IEEE floating point works.

Since what you seem to be doing here is formatting a currency value, I would suggest writing a reusable function to do that so it's done consistently throughout your app.

There are several approaches, however which to use depends on the application

It's not a bug. There is nothing wrong with -0 as a value in IEEE floating point: -0 === 0, x + -0 = x, x * -0 = -0 etc. In arithmetic minus 0 works exactly the same way 0 does.

Usually I would handle the -0.00 when formatting, since only -0.00 "looks wierd", -10.20 is just an overdraft :)

res = res.toFixed(2);
if(res === '-0.00'){
  res = '0.00';
}

I suggest this article to understand IEEE floating point better: What Every Computer Scientist Should Know About Floating-Point Arithmetic

Jon Cooke
  • 92
  • 3
0

javascript and machine in total handle with double as almost infinite number.

when rounding to 2 decimal places, javascript gives the nearest rounded number.

to fix it, use:

var pay = -0.33;
var res = parseFloat(pay) + parseFloat(0.11) + parseFloat(0.22);
res = res.toFixed(2);
return (Math.round(res * 100) / 100);

way better than other's workarounds here will evaluating strings..

EDIT

if you change the round number, better use this:

var fixRound = 2,
    pay = -0.33,
    rounding = Math.pow(10, fixRound),
    res = parseFloat(pay) + parseFloat(0.11) + parseFloat(0.22);
    res = res.toFixed(fixRound );
    return (Math.round(res * rounding ) / rounding );

this way, all you need to change in the code in order for it to work with toFixed(3), toFixed(4),toFixed(5) and so on, is just set fixRound value to be the number you wish.

Ori Refael
  • 2,888
  • 3
  • 37
  • 68
0

Here is a solution I found to prevent toFixed to return negative zero:

fixed_toFixed = (value, prec) => Math.abs(value) < Math.pow(10, -prec) ? (0).toFixed(prec) : value.toFixed(prec);

Ezee
  • 4,214
  • 1
  • 14
  • 29
-1

Actually what is happening here is that there is no initial positive number greater than or equal to the negative number. if you want to get a positive value as a result then the positive number should be greater than or equal to the negative number What i am trying to say is : if you do this: -0.33-0.11+0.44 then you will get a positive zero value as there is an initial positive value greater than all the negative numbers.