Closed
Bug 42134
Opened 24 years ago
Closed 24 years ago
JavaScript should be more lenient comparing (==) floats
Categories
(Core :: JavaScript Engine, defect, P3)
Core
JavaScript Engine
Tracking
()
VERIFIED
INVALID
People
(Reporter: shashi, Assigned: rogerl)
Details
Attachments
(3 files)
The summary I have given does not give an accurate picture of what I am seeing.
I have created two test cases that illustrate the problem so let me upload them
first and then give you the blow-by-blow details.
Reporter | ||
Comment 1•24 years ago
|
||
Reporter | ||
Comment 2•24 years ago
|
||
Reporter | ||
Comment 3•24 years ago
|
||
Testcase #1 - In this document, I have the following JS code:
function MoveText1(start, finish, step, speed){
if (start < finish){
document.getElementById("text1").style.left = start+"px";
start=start+step;
setTimeout("MoveText1("+start+","+finish+","+step+","+speed+")",speed);
}
if (start == 150) {
document.getElementById("text2").style.visibility = "visible";
}
}
This code is started via <body onLoad="MoveText1(0,250,10,5)">. Of key issue is
the second "if" statement. When start hits 150, I want a layer to become
visible. When the testcase is viewed, everything works the way it should.
Testcase #2 - In this document, the JS looks like this:
function FadeText1(start, finish, step, speed){
if (start < finish){
document.getElementById("text1").style.opacity = start;
start=start+step;
setTimeout("FadeText1("+start+","+finish+","+step+","+speed+")",speed);
}
if (start == 0.33) {
document.getElementById("text2").style.visibility = "visible";
}
}
<body onLoad="FadeText1(0.00,0.99,0.03,1)">
As the second "if" states, when start hits 0.33 a layer should become visible.
Viewing the testcase, you will see that *nothing* happens when the target number
is reached.
The two JS functions are identical in structure so it seems strange that it
works in one instance and not another. It looks to me like it comes down to that
"start" number...for some reason Mozilla can't handle decimals...yet it is able
to perform the fade routine without problems using those same decimals. Strange
indeed.
Comment 4•24 years ago
|
||
Here are the values that JavaScript is getting for start on each succesive
call to FadeText1():
0
0.03
0.06
0.09
0.12
0.15
0.18
0.21
0.24
0.27
0.30000000000000004
0.33000000000000007 <---- Uh oh!
0.3600000000000001
So it looks like that the JavaScript floating point equality operator is
being too sensitive: the difference between the target value (0.33) and the
actual value (diff=7e-17) is about two ten-quadrillionths of the target
value.
If you replace
if (start == 0.33)
with
if ((start > 0.32999999) && (start < 0.3300001))
then Testcase 2 works fine.
Confirming on Linux build 2000060908; someone should mark this for all
platofrms. Also, someone should change the summary.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Comment 5•24 years ago
|
||
Changing to all/all per Matt Cline's comments. Lowering severity to normal,
because critical is reserved for things like crashes.
In C/C++, it's the programmer's responsibility to use tolerances instead of ==
to compare floating-point values. It would make sense for the JavaScript spec
to say exactly how floats should work in order to guarantee that something that
works on one platform would work on another, but I don't know if it does or not.
Severity: critical → normal
OS: Windows 98 → All
Hardware: PC → All
Summary: JavaScript is unable to deal with certain arguments → JavaScript should be more lenient comparing (==) floats
Comment 6•24 years ago
|
||
Are there any browsers that *do* give a match? I couldn't figure out how to
test all of the browsers I have using the second testcase (only mozilla did
anything at all), but based on another testcase that doesn't use settimeout or
divs, it seems that all browsers are handling the floating-point part in the
same way. shashi@narain.com, have you tested this on other browsers?
Comment 7•24 years ago
|
||
Reporter | ||
Comment 8•24 years ago
|
||
This is in reply to what Matthew Cline wrote on 2000-06-10 20:55 ---
Excellent catch on the values being passed to JavaScript :-)
>So it looks like that the JavaScript floating point equality operator is
>being too sensitive.
I don't think this is the problem. If I use the equality opertor, it means that
I am expecting a *specific* number and this is born out of how I structured my
JS code. I made very sure that 0.33 *will* be reached. But as your value
analysis clearly shows, Moz never hits 0.33
Reporter | ||
Comment 9•24 years ago
|
||
This is in reply yo what Jesse Ruderman wrote on 2000-06-10 22:05 ---
>have you tested this on other browsers?
Before uploading, I ran my two test cases through IE5. The first TC worked fine
but the second did not because I used the SVG opacity property which is not
supported in IE5.
Your test case was alot better at getting to the essence of this bug. I agree
with you that it has something to do with the floating-point. The additions used
in my JS code are simple...start at 0.00 and keep adding 0.03 until you get to
0.99. Everything works fine from 0.00 to 0.27 but at this point something
bizarre happens. Adding 0.03, any 6th grader will tell you that the answer is
0.30. Moz believes it is 0.30000000000000004...has some new mathmetical concept
been introduced that I am unaware of :-)
To make things even funnier, using the erroneous value of 0.30000000000000004
and adding 0.03 to it, Moz gives out 0.33000000000000007 which is also wrong!!!
Out of curiosity, I ran Jesse's test case in IE5 and it gives the *same* numbers
as Moz does.
In all seriousness, what is going on here??? How did such simple mathmatics
become so complex??? The bottom line is 0.27 + 0.03 = 0.30 not some number
running 17 decimal places long. The implications of this bug are rather far
reaching and affect alot of things.
Reporter | ||
Comment 10•24 years ago
|
||
It's been two weeks since my last comment and nothing seems to have happened
with this bug (it's still "new" and unassigned). Just writing in to check and
see if this bug has not fallen through the cracks.
Comment 11•24 years ago
|
||
Sorry for the delay - taking over QA for the JavaScript Engine group -
I'll try to get an answer for you as soon as possible!
Comment 12•24 years ago
|
||
Hi Shashi,
I discussed this issue with all the engineers on the JavaScript Engine team.
They informed me that this issue occurs because JavaScript conforms to the
ISO standard 16262 (ECMAScript) and the ANSI/IEEE standard 754.
Your "step" increment is 0.03, which does not have an exact binary
representation. Therefore any loops done with this increment value
will eventually incur errors. The behavior of JavaScript is to maintain
as exact a numerical representation as possible at each stage of an
arithmetical operation, and not arbitrarily discard any digits.
I'm afraid I have to mark this bug as invalid. Please see bug 20140,
which deals with the same issue (also marked invalid), and which has
a more complete explanation -
Again, sorry for the delay -
Status: NEW → RESOLVED
Closed: 24 years ago
Resolution: --- → INVALID
Reporter | ||
Comment 13•24 years ago
|
||
Phil --
No apologies neccessary :-) I took a look at bug 20140 and now understand what
is happening here. I fully agree with you that this "bug" is invalid.
In the last comment posted on 20140, waldmer@netscape.com said:
"In JS1.5 you can use Number.toFixed to round the answer to the number of
decimal places you desire."
This will work absolutely perfectly!!! Just to make sure...will Moz be
supporting JS1.5???
Comment 14•24 years ago
|
||
Yes, that is correct: Moz is currently based on JavaScript 1.5
You need to log in
before you can comment on or make changes to this bug.
Description
•