Bug 5856 (js-ieee-double-hurts)

javascript rounding bug

VERIFIED INVALID

Status

()

defect
P3
normal
VERIFIED INVALID
20 years ago
7 days ago

People

(Reporter: AriB, Assigned: norrisboyd)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(URL)

(Reporter)

Description

20 years ago
Just to give one example
14.28 x 9 should be 128.52;
your browser's answer = 128.51999999999998

This bug is also from Netscape 4.5

Updated

20 years ago
Status: NEW → RESOLVED
Last Resolved: 20 years ago
Resolution: --- → INVALID

Comment 1

20 years ago
ECMAScript requires the use of IEEE double precision for numbers.

14.28 correctly rounded as an IEEE double is represented as

1.1100100011110101110000101000111101011100001010001111e3 in base 2, which is

exactly equal to 14.2799999999999993605115378159098327159881591796875 decimal.

Multiplying this value by 9 yields exactly

128.5199999999999942446038403431884944438934326171875.

Per the ECMA spec, this is again rounded to the nearest IEEE double, which is

1.0000000100001010001111010111000010100011110101110000e7 base 2, or

128.51999999999998181010596454143524169921875 decimal.



Why does the result print as 128.51999999999998?  Well, the ECMA spec requires

numbers to be printed with sufficient precision (and no more than that precision)

so that if the printed string were read in again and converted back to a number,

it would round to exactly the same IEEE double that was printed.  Printing 128.52

would be incorrect because the rounding 128.52 to the closest IEEE double yields

128.520000000000010231815394945442676544189453125, which is closer than

128.51999999999998181010596454143524169921875.  Thus we must print

128.51999999999998.

Every other language that uses standard IEEE double-precision arithmetic will

also give this result.  This includes Java and most implementations of C and C++.

Comment 2

20 years ago
Changing component to "Javascript Engine".  "Javascript" component is being
retired.

Updated

20 years ago
Status: RESOLVED → VERIFIED

Comment 3

20 years ago
Verified Invalid

Comment 4

15 years ago
*** Bug 251585 has been marked as a duplicate of this bug. ***
Note that ECMA-262 Edition 3 added Number.prototype.toFixed, which takes a
precision argument telling how many digits after the decimal point to show.  Use
this method well and you won't mind the disparity between finite precision base
2 and the "arbitrary" or "appropriate" precision base 10 that we use every day.

/be
*** Bug 281659 has been marked as a duplicate of this bug. ***

Comment 7

14 years ago
*** Bug 20140 has been marked as a duplicate of this bug. ***

Comment 8

14 years ago
*** Bug 1813 has been marked as a duplicate of this bug. ***
*** Bug 283303 has been marked as a duplicate of this bug. ***
*** Bug 297361 has been marked as a duplicate of this bug. ***

Comment 11

14 years ago
*** Bug 320093 has been marked as a duplicate of this bug. ***

Comment 12

13 years ago
*** Bug 356566 has been marked as a duplicate of this bug. ***

Updated

12 years ago
Duplicate of this bug: 378956
Duplicate of this bug: 393209
Alias: js-ieee-double-hurts
Duplicate of this bug: 408202
Duplicate of this bug: 369803
Duplicate of this bug: 396764
Duplicate of this bug: 409726
Duplicate of this bug: 413965
Duplicate of this bug: 444938
Duplicate of this bug: 452198
Duplicate of this bug: 460943

Updated

11 years ago
Duplicate of this bug: 463163
Duplicate of this bug: 466822

Updated

11 years ago
OS: Windows 98 → All
Hardware: PC → All
Duplicate of this bug: 516355

Updated

10 years ago
Duplicate of this bug: 520754

Updated

10 years ago
Duplicate of this bug: 190303

Updated

10 years ago
Duplicate of this bug: 280544
Duplicate of this bug: 538209
Duplicate of this bug: 557530
Duplicate of this bug: 582086
Duplicate of this bug: 618839
Duplicate of this bug: 656887
Duplicate of this bug: 699645
Duplicate of this bug: 832727
Duplicate of this bug: 839324

Comment 39

6 years ago
Duplicate of the Bug: 15* 1.33 (instead of expected 19.95 it return 19.950000000000003)
Duplicate of this bug: 1118287

Comment 41

2 years ago
(37 + Math.pow(2, -1) + Math.pow(2, -3) + Math.pow(2, -5)) * 1e-32
3.7656250000000003e-31
in my string to number converter, it comes out without the 0000000003 error amount.

Comment 42

2 years ago
at least into the console.

Comment 43

2 years ago
reopen this bug?

Comment 44

2 years ago
by the way, the representation of the mantissa is best represented in binary form (base 2). so that's what I have done. even successive adds above have not deterred my converter from coming out with the right result. does the debugger contain an old/defective IEEE in its JS engine? I don't know if it uses its own JS engine or whether it uses the browser's. to me it's only important to get right results. this should come out 
this should come out 
(37 + Math.pow(2, -1) + Math.pow(2, -3) + Math.pow(2, -5)) * 1e-32
3.765625e-31
but came out 
(37 + Math.pow(2, -1) + Math.pow(2, -3) + Math.pow(2, -5)) * 1e-32
3.7656250000000003e-31
in the 54.0.1 console.
same problem with:

$('.chnagenumber').val()--> "3" 
$('.chnagenumber').val()*0.0001 --->"0.00030000000000000003"


my dirty solution:

alert(((0.0001*3)*1000000000000)/1000000000000); it display 0.0003 correcty
https://en.wikipedia.org/wiki/IEEE_754

11 mar 2019 4:56 pm edt:
(1)to Waldemar Horwat's comment:
'Every other language that uses standard IEEE double-precision arithmetic will
also give this result. This includes Java and most implementations of C and C++.'

now c produce better result:
//math_test.c
//compile-command:gcc -o math_test math_test.c
#include <stdio.h>
int main ()
{
/* javascript-eval-result,javascript-standard-arithmetic-result:
(1)defect:2.9+2.8=5.699999999999999
(2)defect:2.9-2.8=0.10000000000000009
(3)defect:2.9-2=0.8999999999999999
(4)not defect:2.9X2=5.8
(5)defect:2.9X2.3=6.669999999999999
(6)not defect:2.8/1.4=2
(7)not defect:2.8/4=0.7
(7)not defect:2.8/3=0.9333333333333332
/
printf("2.9+2.8=%f",2.9+2.8); // 2.9+2.8=5.700000
printf("\n2.9-2.8=%f",2.9-2.8); // 2.9-2.8=0.100000
printf("\n2.9-2=%f",2.9-2); // 2.9-2=0.900000
printf("\n2.9x2=%f",2.9
2); // 2.9x2=5.800000
printf("\n2.9x2.3=%f",2.9*2.3); // 2.9x2.3=6.670000
printf("\n2.8/1.4=%f",2.8/1.4); // 2.8/1.4=2.000000
printf("\n2.8/4=%f",2.8/4); // 2.8/4=0.700000
printf("\n2.8/3=%f",2.8/3); // 2.8/3=0.933333
printf("\n");

return 1;
}

(2)to brendan eich's comment 'Note that ECMA-262 Edition 3 added Number.prototype.toFixed, which takes a
precision argument telling how many digits after the decimal point to show. Use
this method well':
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
from google(Number.prototype.toFixed)result 1
will also round-up result for 2.8/3=0.9333333333333332=0.9.
if that result remain 0.9333333333333332 then that's better because:
linuxmint-18.2->gnu-calculator says:
0.9333333333333332 x 3 = 2.8
0.9 x 3 = 2.7
0.93 x 3 = 2.79.

a javascript-htm-test-file:
<!--- defect_eval.htm:
(1)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval from google(javascript evalulate math)
should contain warning about this eval-defect:
(2)mozilla should write warning about simple-arithmetic-defect
like in page
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
should contain warning saying 'tips:did you know that
in javascript 2.9-2.8 = 0.10000000000000009.please make your own
subtraction-function,addition-function,multiplication-function'
-->

<script language="javascript">
//simple-arithmetic-defect
document.writeln('simple-arithmetic-defect');
document.writeln('<br>(1)defect:2.9+2.8='+(2.9+2.8)); // 5.699999999999999 <-- defect
document.writeln('<br>(2)defect:2.9-2.8='+(2.9-2.8)); // 0.10000000000000009 <-- defect
document.writeln('<br>(3)defect:2.9-2='+(2.9-2)); // 0.8999999999999999 <-- defect
document.writeln('<br>(4)not defect:2.9X2='+(2.92)); // 5.8 <-- not defect
document.writeln('<br>(5)defect:2.9X2.3='+(2.9
2.3)); // 6.669999999999999 <-- defect
document.writeln('<br>(6)not defect:2.8/1.4='+(2.8/1.4)); // 2 <-- not defect
document.writeln('<br>(7)not defect:2.8/4='+(2.8/4)); // 0.7 <-- not defect
document.writeln('<br>(7)not defect:2.8/3='+(2.8/3)); // 0.9333333333333332 <-- not defect

//eval-defect
document.writeln('<br><br>eval-defect');
document.writeln('<br>(1)defect:2.9+2.8='+eval(2.9+2.8)); // 5.699999999999999 <-- defect
document.writeln('<br>(2)defect:2.9-2.8='+eval(2.9-2.8)); // 0.10000000000000009 <-- defect
document.writeln('<br>(3)defect:2.9-2='+eval(2.9-2)); // 0.8999999999999999 <-- defect
document.writeln('<br>(4)not defect:2.9X2='+eval(2.92)); // 5.8 <-- not defect
document.writeln('<br>(5)defect:2.9X2.3='+eval(2.9
2.3)); // 6.669999999999999 <-- defect
document.writeln('<br>(6)not defect:2.8/1.4='+eval(2.8/1.4)); // 2 <-- not defect
document.writeln('<br>(7)not defect:2.8/4='+eval(2.8/4)); // 0.7 <-- not defect
document.writeln('<br>(7)not defect:2.8/3='+eval(2.8/3)); // 0.9333333333333332 <-- not defect
</script>

(In reply to arnon81 from comment #46)

11 mar 2019 4:56 pm edt:
(1)to Waldemar Horwat's comment:
'Every other language that uses standard IEEE double-precision arithmetic will
also give this result. This includes Java and most implementations of C and C++.'

now c produce better result:
//math_test.c
//compile-command:gcc -o math_test math_test.c
#include <stdio.h>
int main ()
{
/* javascript-eval-result,javascript-simple-arithmetic-result:
(1)defect:2.9+2.8=5.699999999999999
(2)defect:2.9-2.8=0.10000000000000009
(3)defect:2.9-2=0.8999999999999999
(4)not defect:2.9X2=5.8
(5)defect:2.9X2.3=6.669999999999999
(6)not defect:2.8/1.4=2
(7)not defect:2.8/4=0.7
(7)not defect:2.8/3=0.9333333333333332
/
printf("2.9+2.8=%f",2.9+2.8); // 2.9+2.8=5.700000
printf("\n2.9-2.8=%f",2.9-2.8); // 2.9-2.8=0.100000
printf("\n2.9-2=%f",2.9-2); // 2.9-2=0.900000
printf("\n2.9x2=%f",2.9
2); // 2.9x2=5.800000
printf("\n2.9x2.3=%f",2.9*2.3); // 2.9x2.3=6.670000
printf("\n2.8/1.4=%f",2.8/1.4); // 2.8/1.4=2.000000
printf("\n2.8/4=%f",2.8/4); // 2.8/4=0.700000
printf("\n2.8/3=%f",2.8/3); // 2.8/3=0.933333
printf("\n");

return 1;
}

(2)to brendan eich's comment 'Note that ECMA-262 Edition 3 added Number.prototype.toFixed, which takes a
precision argument telling how many digits after the decimal point to show. Use
this method well':
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
from google(Number.prototype.toFixed)result 1
will also round-up result for 2.8/3=0.9333333333333332=0.9.
if that result remain 0.9333333333333332 then that's better because:
linuxmint-18.2->gnu-calculator says:
0.9333333333333332 x 3 = 2.8
0.9 x 3 = 2.7
0.93 x 3 = 2.79.

a javascript-htm-test-file:
<!--- defect_eval.htm:
(1)https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval from google(javascript evalulate math)
should contain warning about this eval-defect:
(2)mozilla should write warning about simple-arithmetic-defect
like in page
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
should contain warning saying 'tips:did you know that
in javascript 2.9-2.8 = 0.10000000000000009.please make your own
subtraction-function,addition-function,multiplication-function'
-->

<script language="javascript">
//simple-arithmetic-defect
document.writeln('simple-arithmetic-defect');
document.writeln('<br>(1)defect:2.9+2.8='+(2.9+2.8)); // 5.699999999999999 <-- defect
document.writeln('<br>(2)defect:2.9-2.8='+(2.9-2.8)); // 0.10000000000000009 <-- defect
document.writeln('<br>(3)defect:2.9-2='+(2.9-2)); // 0.8999999999999999 <-- defect
document.writeln('<br>(4)not defect:2.9X2='+(2.92)); // 5.8 <-- not defect
document.writeln('<br>(5)defect:2.9X2.3='+(2.9
2.3)); // 6.669999999999999 <-- defect
document.writeln('<br>(6)not defect:2.8/1.4='+(2.8/1.4)); // 2 <-- not defect
document.writeln('<br>(7)not defect:2.8/4='+(2.8/4)); // 0.7 <-- not defect
document.writeln('<br>(7)not defect:2.8/3='+(2.8/3)); // 0.9333333333333332 <-- not defect

//eval-defect
document.writeln('<br><br>eval-defect');
document.writeln('<br>(1)defect:2.9+2.8='+eval(2.9+2.8)); // 5.699999999999999 <-- defect
document.writeln('<br>(2)defect:2.9-2.8='+eval(2.9-2.8)); // 0.10000000000000009 <-- defect
document.writeln('<br>(3)defect:2.9-2='+eval(2.9-2)); // 0.8999999999999999 <-- defect
document.writeln('<br>(4)not defect:2.9X2='+eval(2.92)); // 5.8 <-- not defect
document.writeln('<br>(5)defect:2.9X2.3='+eval(2.9
2.3)); // 6.669999999999999 <-- defect
document.writeln('<br>(6)not defect:2.8/1.4='+eval(2.8/1.4)); // 2 <-- not defect
document.writeln('<br>(7)not defect:2.8/4='+eval(2.8/4)); // 0.7 <-- not defect
document.writeln('<br>(7)not defect:2.8/3='+eval(2.8/3)); // 0.9333333333333332 <-- not defect
</script>

addition 11 mar 2019 5:33 pm edt--------------
#reword# /* javascript-eval-result,javascript-standard-arithmetic-result:
#to# /* javascript-eval-result,javascript-simple-arithmetic-result:
i write this addition by clicking 'reply to this comment' on an icon located right-side of my comment.

http://wortel.ucoz.com/calculator.htm#17_apr_2019_6_29_pm_edt
maybe has correct-arithmetic,function division may produce many decimal-digit if those decimal-digit are all different not repetitive.
arithmetic-code is located in
find '//start math-arithmetic-function','//end math-arithmetic-function'

You need to log in before you can comment on or make changes to this bug.