1

I was doing some money calculation and I got the number -0. This number -0 does not exists, since 0 does not have a sign. Why is this happening? I know the original price has more digits on my bd. but anyway this behaviour thing is weird anyway.

So I'm using this math expression: I pick the item price and subtract the discount, then I round it up.

(19.99923-20).toFixed(2)

And I get "-0.00" !? this is ugly to display. I tried using the Number() to make it a "real number", but

 Number((19.99923-20).toFixed(1))

will appear as "-0".

What's wrong with javascript, there is no number -0, it should be just "0"?

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
Miguel
  • 3,349
  • 2
  • 32
  • 28
  • 5
    Possible duplicate of [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) // Your value _is not_ zero, it is ever so slightly less than zero - and that where the minus sign comes from. – CBroe Oct 27 '16 at 20:08
  • Its not really a problem of floating point, because when i convert to Number(x) it is no more a floating thing because it came .tofixed digits to a number. – Miguel Oct 27 '16 at 20:09
  • 3
    Numbers in Javascript are IEEE 754 floating point numbers. This representation known [a signed zero](https://en.wikipedia.org/wiki/Signed_zero). What's special here is that Javascript knows no Integers but even whole numbers are floating point. – Holger Just Oct 27 '16 at 20:10
  • @CBroe yes, but when i run the Number(X) i was expecting it to conver it to a valid number lets say.. because for example Number("-0") will still be -0, odd, because -0 is not a real number, it should expect just 0, since 0 is not signed. What is the floating point of ZERO? zero offcourse, but not in this case as you see > 0===-0 so it should display just 0... and plus i cannot make it positive for display, by evaluating the if(0<-0) then make it =0, because -0<0 = false – Miguel Oct 27 '16 at 20:15
  • 2
    Floating point numbers have a negative zero because of how the negative sign is implemented in IEEE 754. Even though it seems counterintuitive, you can do `if( mynumber === 0 ) { mynumber = 0; }` to get rid of the minus sign. – JJJ Oct 27 '16 at 20:20
  • Js little gems. – Miguel Oct 27 '16 at 20:29
  • @JJJ To get rid of the sign, just use `Math.abs` :-) – Bergi Oct 27 '16 at 20:31
  • To be fair, this behavior doesn't have anything to do with JS. This is how it works in all programming languages that implement IEE 754 floating point numbers, which is almost all of them. – JJJ Oct 27 '16 at 20:33
  • @Bergi no Because i dont know if the number can actually be -1 for example.. – Miguel Oct 27 '16 at 20:34

2 Answers2

0

JavaScript keeps sign with floating negatives close to 0, either using Math.round() or toFixed(), both can get you a -0. Solved that applying a quick fix, which consists in checking if our number enters that range in between 0 and -0.005 (rounded to -0.01 later). Considered 2 floating digits as your example works with money, so I considered a difference of 1 cent relevant:

var num=19.99923-20;
    if(num>-0.005 && num<0){
        num=0; //we set to '0' all -0 
    }else{
        num=num*100;
        num=Math.round(num);
        num=num/100;
    /*or
      num=num.toFixed(2);
    but this way we convert number to string*/

    }

Hope it helps.

adr1Script
  • 109
  • 5
0

toFixed converts a number to string, not a number. So the -0.00 you are seeing is a string. Its the result of converting

19.99923-20 // which is about
-0.0007699999999992713  // in internal representation

to a string using the toFixed method in ECMAscript standards, which initialises the result to "-" for negative numbers and proceeds to convert the absolute (positive) value of the number being converted.

Converting the string "-0.00" back to a number with either parseFloat("-0.00") or Number("-0.00") returns a positive zero number representation (javscript stores numbers using the IEEE 754 standard for double precision float representation, which does have a negative zero value, but it's not the problem here.)

Looking at how toFixed works suggests the only problem is with a "-0.00" result, which can be checked using string comparison:

 var number = 19.99923-20;
 var str = number.toFixed(2);
 if( str == "-0.00")
     str = "0.00";

Alternatively you could consider using a conversion routine which never returns a negatively signed zero string such as:

function convertFixed( number, digits) {
    if(isNaN(number))
        return "NaN";

    var neg = number < 0;
    if( neg)
        number = -number;
    var string = number.toFixed(digits);
    if( neg && Number(string) === 0) // negative zero result
        neg = false;
    return neg ? "-" + string : string;
}
traktor
  • 17,588
  • 4
  • 32
  • 53