Re: While loop with addition goes weird (binary float rounding error)
by LanX (Cardinal) on Apr 08, 2018 at 13:08 UTC

 [reply] 

Thanks for your reply. But to me, your answer is as difficult to understand as my problem ;) Can you explain it more simplistic? Maybe with example on how to do it? I'm just trying to add numbers here.
 [reply] 

 [reply] 

We can almost always ignore floatingpoint errors and round our results with printf. Unfortunately there is no "simplistic" way to recognize the rare cases where this is a bad idea (Or what to do about it if you really have one). The documents already cited are not easy to read! Be assured that they to not require knowledge of any math beyond elementary algabra  only a commitment to learn.
 [reply] 


Re: While loop with addition goes weird
by davido (Cardinal) on Apr 08, 2018 at 17:28 UTC

I gave a more thorough explanation of this in Re: shocking imprecision. But the essential component is that we tend to think nothing of expressing 1/3rd as 0.33 in base 10, and casually understand out of habit that 0.33 + 0.33 + 0.33 is strictly 0.99, but implicitly 1 when dealing with decimal representations of fractions. However we are not as accustomed to dealing with binary fractional arithmetic.
In base 10, any fraction that can be expressed as k/((2^n)*(5^m)) will have a terminating expansion, and any that cannot be expressed as such will not. In Base 2, the number must be able to be expressed as k/2^n to have a terminating expansion, and any that cannot be expressed as such will not terminate, meaning it cannot be expressed in a finite number of bits.
Let's look at 0.01: 0.01 is approximately 1000/(2**16) or 1000/(2**17). Both are terrible approximations. Closer would be 10000/(2**20). But that's still a pretty poor approximation. And your calculation is relying on exactness, not approximations.
 [reply] 
Re: While loop with addition goes weird
by hippo (Chancellor) on Apr 08, 2018 at 15:36 UTC

 [reply] 
Re: While loop with addition goes weird
by Laurent_R (Canon) on Apr 08, 2018 at 14:30 UTC

Computers are notoriously bad at computing with decimal numbers. That includes most programming languages.
If you want accurate arithmetic, you might want to try using Perl 6:
> my $size = 0.01;
0.01
> my $step_size = 0.01;
0.01
> $size += $step_size while $size < 5;
Nil
> say "FINAL: $size";
FINAL: 5
;)
 [reply] [d/l] 
Re: While loop with addition goes weird
by jimpudar (Pilgrim) on Apr 08, 2018 at 16:57 UTC

Hello chiel,
You should definitely read the pages LanX linked to. The second especially is required reading for anyone who wants to write a computer program.
However, I did want to point out you can use the bignum pragma to get Perl 5 to do what you want:
$ perl e '
use warnings;
use bignum;
my $size = 0.01;
my $step_size = 0.01;
while($size < 5){
$size = $size + $step_size;
print $size."\n";
}
print "FINAL: ".$size."\n";'
...
4.94
4.95
4.96
4.97
4.98
4.99
5
FINAL: 5
Best,
Jim  [reply] [d/l] 
Re: While loop with addition goes weird
by poj (Abbot) on Apr 08, 2018 at 14:14 UTC

 [reply] 
Re: While loop with addition goes weird
by Anonymous Monk on Apr 08, 2018 at 14:03 UTC

As the articles that you've already been pointed to say, computers use a floatbinary representation. The number 1/10 does not have an exact representation in base2 floats, much as 1/3 does not have an exact representation in a base10 float. Computers can handle this problem by using decimal (BCD = BinaryCoded Decimal) arithmetic, but Perl does not directly expose this type. One pragmatic solution to your problem might be to count using integers, where the integer is the desired number multiplied by 100. Then, each time, calculate the float by casting the integer to a float and dividing it by 100. Because this is done each time, errors do not accumulate. Many database systems employ a variation of this "scaled integer" strategy to handle their currency data type.  [reply] 