0

I have the following function:

var a = 0.1;
var b = 0.2;

function checkValue(){
    if(a + b === 0.3){
        alert('statement is true');   
    }
    else {
        alert('statement is false');   
    }
}

checkValue();

This function evaluates to false?? Here is fiddle

Now, the same function with different decimals that also equal 0.3:

var a = 0.15;
var b = 0.15;

function checkValue(){
    if(a + b === 0.3){
        alert('statement is true');   
    }
    else {
        alert('statement is false');   
    }
}

checkValue();

evaluates to true.

Has anyone run into this before? If so are there languages commonly used for web applications that do not do this?

HelloWorld
  • 2,480
  • 3
  • 28
  • 45

6 Answers6

1

Floating numbers are inaccurate in JS. It's luck that the second example evaluates to true for you... it may not on someone else's computer. For workarounds, see this thread: How to deal with floating point number precision in JavaScript?

Community
  • 1
  • 1
Hamza Kubba
  • 2,259
  • 14
  • 12
  • The odd thing is that the second example consistently evaluates to true and the first consistently evaluates to false. I just tried in 3 different browser consoles on 3 different machines. I get that js doesn't parse decimals perfectly, but if it is just luck why do the two functions produce persist in producing the same results? – HelloWorld Apr 25 '14 at 04:53
  • Open your javascript console to see part of the reason why... run `console.log(0.1 + 0.2)` and `console.log(0.15 + 0.15)`. The second one probably has 20 digits before a non-zero or something, and it's getting chopped off so it happens to evaluate to 0.3. The point is, Javascript floating numbers are unreliable for direct comparisons like that. – Hamza Kubba Apr 25 '14 at 04:57
  • Yes, you are correct. the first example evaluates to 0.30000000000000004 thanks for the knowledge! – HelloWorld Apr 25 '14 at 05:02
  • @HamzaKubba, it is not JavaScript math that is "unreliable" or "broken", it is the general [binary floating point arithmetic](http://stackoverflow.com/questions/588004/is-floating-point-math-broken). JavaScript is is doing nothing special, just using 64bit double numbers the way the FPU handles them. It is only showing a more that complete representation of the internal binary representation where other languages/compilers apply more sensible rounding or rounding to much less accuracy by default. – Lutz Lehmann Apr 25 '14 at 11:02
  • Never said they were unreliable or broken, just that they are "unreliable for direct comparisons like that". That's a good description of how they work though. – Hamza Kubba Apr 25 '14 at 20:22
1

Floating point numbers are inaccurate in most programming languages due to the way that they store values.

So, 0.1 + 0.2 == 0.3 evaluates to false and only 0.3 will ever == 0.3.

It's actually interesting how many large-scale issues this has caused in deployed software and major companies.

AstroCB
  • 12,337
  • 20
  • 57
  • 73
  • I thought it was an interesting issue too. – HelloWorld Apr 25 '14 at 04:57
  • `3/10 == 0.3; // true` – cookie monster Apr 25 '14 at 05:05
  • Any company losing money on this richly deserves to (do you have a link to a true story or is this just an urban myth?). This is known and expected behavior since the invention of binary floating point formats, not some kind of Pentium bug. – Lutz Lehmann Apr 25 '14 at 12:53
  • @LutzL http://en.wikipedia.org/wiki/Pentium_FDIV_bug – AstroCB Apr 25 '14 at 14:17
  • Yes, that's the Pentium bug. But the general and unavoidable peculiarities of floating point formats in binary representations, which are in question here, are in an absolutely different category. – Lutz Lehmann Apr 25 '14 at 14:24
  • @cookie monster - It is true but why? I am new to js and programming in general and I am trying to understand. It seems like 3/10 should = Infinity logically. – HelloWorld Apr 25 '14 at 19:42
1

Try this FIDDLE.

its working.

use this code in javascript

variable.toFixed(2)
Kaushal Khamar
  • 2,097
  • 1
  • 17
  • 23
  • If you amend the alert string to `alert('statement is true:\n '+a.toFixed(25)+"\n+"+b.toFixed(25)+"\n="+(a+b).toFixed(25));` then you see what exactly happens internally. A much greater curiousity is that by this rounding arithmetic, `0555+1110=4440`. – Lutz Lehmann Apr 25 '14 at 11:09
0

You can fix the floating point problem by fixing the decimal like this:

if((a + b).toFixed(1) == 0.3){
 alert('statement is true');   
}else{
 alert('statement is false');   
}
AstroCB
  • 12,337
  • 20
  • 57
  • 73
jhyap
  • 3,779
  • 6
  • 27
  • 47
  • Yep that works. I will try it on larger floating points to test limits. – HelloWorld Apr 25 '14 at 04:56
  • There is no problem and this is not a fix. That the binary (truncated) floating point numbers represent different and sometimes unintuitive intervals than the decimal truncated numbers is expected and well-known. To use rounding to extract the valid decimal places is the recommended procedure. You need not be timid, toFixed(10) would work as well for numbers smaller than 1e5. – Lutz Lehmann Apr 25 '14 at 12:48
0

Try this

a + b = 0.300004 So you will have to use .toFixed()

var a = 0.1;
var b = 0.2;

function checkValue(){
    var answer = a + b;
    alert(answer.toFixed(1))
if(answer === 0.3){
 alert('statement is true');   
}
else {
 alert('statement is false');   
}
}

checkValue();
Geo
  • 3,160
  • 6
  • 41
  • 82
0

When you add those together, for some odd reason it returns as 30000000000000004. To fix this, as listed above, you can use the .toFixed(1), which rounds to a certain decimal place, based on the argument number you give it. There are other ways to round as well. You can do Math.round(), but beware as this cuts of ANY decimal places. Hope this helps a bit.

Brendan
  • 1,399
  • 1
  • 12
  • 18