4

I am trying to fix the number to 2 digits after decimal and for that i am using toFixedfunction of javascript. Below are the strange results i am getting, please check and help me.

var number = 11.995;
number.toFixed(2); // giving me 11.99 which is correct

var number = 19.995;
number.toFixed(2); // giving me 20.00 which is incorrect

Can anyone tell me why it is happening.

Thanks for your help.

5 Answers 5

6

This is how floating point math works. The value 19.995 is not exact binary (base 2). To make it more clear, think of an exact number when you divide 10/3.

For more in-depth explanations, read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

In your case you can work with strings instead (at least it seems like that is what you want):

number.toString().substr(0, n);

Or define a function like this (made in 2 minutes, just an example):

Number.toFixed = function(no, n) {
    var spl = no.toString().split('.');
    if ( spl.length > 1 ) {
        return spl[0]+'.'+spl[1].substr(0,n);
    }
    return spl[0];
}

Number.toFixed(19.995, 2); // 19.99
Sign up to request clarification or add additional context in comments.

2 Comments

@RobW correct, but it was not meant to be an exact replacement just in theory. But thanks!
0,4 only gives 1 decimal in this case. You'd better use indexOf to detect the dot, or just use a RegExp for a one-liner: /-?\d+(\.\d{0,2})?/. Note: The regexp is not complete, it doesn't deal with exponents.
1

toFixed rounds the value. Since 19.995 is exactly halfway between 19.99 and 20.00, it has to choose one of them. Traditionally, rounding prefers the even result (this prevents bias, since round-ups and round-downs will be equal).

4 Comments

It doesn’t "choose". 19.995 is not exactly halfway, since floating numbers are not exact in javascript. You can test this by adding 19.999991 + 0.000004 wich equals 19.999995000000002.
Some floating point fractions are exact, though, such as 0.5. However, it looks like I was wrong about it rounding to even, it always rounds up. 0.5.toFixed(0) is 1, 1.5.toFixed(0) is 2.
No it doesn’t always round up, and that was the original question. F.ex (11.995).toFixed(2) is 11.99
That's because of what you said earlier, that it isn't exact. The one that are exactly halfway round up.
1

I have create a function which done all for me..

    function toFixed(number, precision) {
        var multiplier = Math.pow(10, precision + 1),
            wholeNumber = Math.floor(number * multiplier);
        return Math.round(wholeNumber / 10) * 10 / multiplier;
    }

   //Call this function to retrive exect value
    toFixed((+adjustmentval), 2);

1 Comment

My thoughts exactly! Too bad toFixed doesn't do that - how are we supposed to know there might be a problem? Well, I guess that we should be aware(?)...
0

David has answered your doubt I'm guessing. Just providing an alternate solution here.

You can use the Math.floor() method of the Math object for this.

Something like this, Math.floor(number*100)/100

Comments

0

Can anyone tell me why it is happening.

The IEEE-754 double-precision binary floating point number standard used by JavaScript's number type (and similar times in several other languages) does not perfectly store all numbers, it stores some numbers imprecisely, in a way that lets it A) Store them in just 64 bits, and B) Calculate with them quickly.

For 11.995, the actual value is 11.99499988555908203125, just slightly less than 11.995.

For 19.995, the actual value is 19.9950008392333984375, just slightly more than 19.995.

That explains why when you round them using the usual round-to-nearest-half-up operation, 11.995 (which is really 11.99499988555908203125) rounds down to 11.99 but 19.995 (which is really 19.9950008392333984375) rounds up to 20.00.

(This site has a handy calculator for visualizing this stuff.)

More here on SO:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.