Forum Moderators: coopster

Message Too Old, No Replies

Simple FOR loop does not reach the end?!

Some kind of rounding error?!

         

penders

11:22 am on Oct 14, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



An example...

(1) This works OK and outputs the nos 0, 0.1, 0.2, ...., 0.9, 1

for($myvar=0; $myvar<=1; $myvar+=0.1) { 
echo $myvar.', ';
}

(2) This does not reach the end (IMO) - outputs the nos 0, 0.01, 0.02, ...., 0.98, 0.99

for($myvar=0; $myvar<=1; $myvar+=0.01) { 
echo $myvar.', ';
}

Why does example (2) not reach 1 ?

Little_G

11:47 am on Oct 14, 2008 (gmt 0)

10+ Year Member



Hi,

Seems to be a problem with 'hidden precision', see PHP: Floating point numbers - User Contributed Notes [php.net]

This works:

for($myvar=0; round($myvar,2)<=1; $myvar+=0.01) {  
echo $myvar.', ';
}

Andrew

[edited by: Little_G at 11:49 am (utc) on Oct. 14, 2008]

penders

1:44 pm on Oct 14, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ah OK, thanks for that! The penny has finally dropped! Mmmm... appears to be an issue checking floats for equality period. Dang, I've encountered this many times before but I hadn't appreciated what was really going on! (Incidentally, it's the same with JavaScript ...and other languages I guess.)

This particular example could be changed to check for integer equality, which obviously works:

for($myvar=0; $myvar<=100; $myvar++) {  
echo ($myvar/100).', ';
}

Regarding this floating point (im)precision, you can 'see' it in action if you do something like:

for($myvar=0; $myvar<=1; $myvar+=0.01) {  
echo number_format($myvar,20).'<br />';
}

Which outputs...

0.00000000000000000000
0.01000000000000000021
0.02000000000000000042
0.02999999999999999889
0.04000000000000000083
0.05000000000000000278
0.05999999999999999778
0.07000000000000000666
0.08000000000000000167
0.08999999999999999667
0.10000000000000000555
:
etc.

$myvar never really equals anything you might expect, unless you intervene and round() the precision.