PDA

View Full Version : absolutelly bizare substract loop



Kor
Feb 10th, 2005, 01:45 PM
That is really bizzare: :eek:



<script language="JavaScript" type="text/JavaScript">
var a = 1;
var b = 0.1;
function bla(){
if(a==0){
clearTimeout(x);
}
else{
a=a-b;
alert(a);
var x= setTimeout('bla()',2000)//leave it at higher value
}
}
onload=bla;
</script>


first loop the alert is 0.9, second is 0.8, third is, surprise, 0.7000000000000001. Next values are floated so that the value never reach 0 (this is the reson for I set the delay on 2 secs, to avoid unstopable loop)

-----------
in fact the problem can be reduced at

alert(0.8-0.1). Furthermore, if I substract anything from 0.8 (except 0 and 0.8) the problem is still there...

That is absolutely weird to me :eek: ... Any explanation?

:D

codegoboom
Feb 10th, 2005, 02:49 PM
Seems like I read something about that... Why does JScript have rounding errors? (http://blogs.msdn.com/ericlippert/archive/2003/09/15/53000.aspx)

Kor
Feb 10th, 2005, 03:05 PM
a, great... I see the explanation now. Some floated numbers are not be represented exactly in binary. so that small errors may occure... Thanks, I was affraid I would not have been able to sleep tonight trying to understand that "enigma" :D

liorean
Feb 10th, 2005, 03:09 PM
No secret there - it's a problem related to the floating point representation used by most computers. It's binary. That means that you can only accurately represent decimal numbers if they can be represented as sums of a sequence of numbers representable as 2^-n where n is a positive integer. Let me give you a few examples:


Simple:
0.5 = 1/2 = 2^-1
0.25 = 1/4 = 2^-2
0.125 = 1/8 = 2^-3
0.0625 = 1/16 = 2^-4
...

Less simple:
0.75 = 1/2 + 1/4 = 2^-1 + 2^-2

Not accurately representable:
0.8 = 1/2 + 1/4 + 1/32 + 1/64 + 1/512 + 1/1024 + 1/8192 + 1/16384 + 1/131072 + 1/26144 ... = 2^-1 + 2^-2 + 2^-5 + 2^-6 + 2^-9 + 2^-10 + 2^-13 + 2^-14 + 2^-17 + 2^-18...


See the problem? Something that isn't precisely representable will be approximated by adding a series of smaller and smaller precise numbers. However, the problem with this approach is that you can't use an infinite amount of fractions due to storage limits - thus it's necessary to truncate.



The solution is simple: Use integers instead, and just divide by ten when displaying them.

0x00F18305
Feb 10th, 2005, 03:24 PM
It's not bizzarre at all !!...JavaScript uses the IEEE-754 double presicion in arithmetic operations

floating point representation has an inherent error in the representation of number systems, refer to this link for more information on this standard: IEEE-754 (http://stevehollasch.com/cgindex/coding/ieeefloat.html)

This type of error is in fact the reasn why you should NEVER use floating point numbers as the stopping condition in otherwise infinite loops.

To solve your problem you can use one of two methods:

1. replace the if(a==0) with if(a<=0) ...this is the best solution

2. you can add the following line after the subtraction:
a = Math.round(a*10)/10;

:thumbsup:

Kor
Feb 10th, 2005, 03:47 PM
The solution is simple: Use integers instead, and just divide by ten when displaying them.


I have had already did that. I have put this thread here only because I have not understood at the moment why was that happended. Now I see, Thanx all for the replies.