adismaug has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,
I have a script that make a simple math addition.
The strange thing is that it adds some floating point numbers.
The script:
```\$count = 895.3;
while (\$count <= 900) {
\$count += 0.01;
print "\$count\n";
}

The output:
895.31
895.32
895.33
895.34
895.35
895.36
895.37
895.38
895.39
895.4
895.41
895.42
895.43
895.44
895.45
895.46
895.47
895.48
895.49
895.5
895.51
895.52
895.53
895.54
895.55
895.56
895.57
895.58
895.59
895.6
895.61
895.62
895.63
895.64
895.65
895.66
895.67
895.68
895.69
895.7
895.71
895.72
895.73
895.74
895.75
895.76
895.77
895.78
895.79
895.8
895.809999999999
895.819999999999
895.829999999999
895.839999999999
895.849999999999
895.859999999999
895.869999999999
895.879999999999
895.889999999999
895.899999999999
895.909999999999
895.919999999999
895.929999999999
895.939999999999
895.949999999999
895.959999999999
895.969999999999

Replies are listed 'Best First'.
Humans have too many fingers
by LanX (Cardinal) on Jul 18, 2009 at 12:22 UTC

#### Rule of Thumb:

To calculate dollars "accurately" with 2 decimal places, you need
to calculate right from the beginning in cents as integers!

So just calculate with integers in the desired accuracy and shift the decimal point afterwards˛!

#### Background:

Floats are not accurate with decimal fractions because the computer "has only two fingers".

#### Experiment

Just try to express 1/3 accurately in decimal system!

And now imagine you're an alien with 3 fingers 4 and you have only computers that calculate in decimal fractionsą... wouldn't this annoy you, too?

#### Conclusion

Humans have too many fingers! Downsizingł to octal system would do it...

Cheers Rolf

Footnotes:

Many modern processors also have support for Binary Coded Decimal (BCD) calculations, including Pentium, Itanium, PA-RISC, IBM mainframes and others. These capabilities can be used with assembly code programming or use of appropriate libraries. Standardization of decimal arithmetic was added to the new IEEE 754 2008 standard.

So just calculate with integers in the desired accuracy and shift the decimal point afterwards˛!

I agree , that's what I'd do also

by FunkyMonk (Chancellor) on Jul 18, 2009 at 12:02 UTC
That's the nature of floating point values. They are just (very accurate) approximations. See this Wikipedia article for more.

For example

```\$ perl -e '\$a+=0.1 for 1..10; print \$a - 1'
-1.11022302462516e-16

Update^2: Eventually found the FAQ

by biohisham (Priest) on Jul 18, 2009 at 12:23 UTC
it seems like you want to restrict yourself to 2 digits after the point. Hence instead of print,you use "printf or sprintf" functions in the type of notation you want, in this case the "f" for floating numbers preceded by the digit capacity, that is 3 digits before the point and two digits after the point, preceded by %, so it would look like this printf "%6.2f", notice, the point is included in the count hence 6.2 instead of 5.2(Updated after Albannach reply)
```\$count = 895.3;
while (\$count <= 899.99) {
\$count += 0.01;
printf "%6.2f",\$count; #(updated)
print "\n";
}
the numbers in computers are approximations and hence comes such issues esp while using higher level programming languages such as Perl.
Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind
A (pretty common) nit to pick here: the 3 in %3.2f is not the number of digits before the decimal, it's the minimum total width of the resulting field, including the decimal. So if you really want 3 digits, a decimal and 2 digits, then you need %6.2f. This is a minimum and the digits to the left of the decimal will still be printed, so your example of 895.3 still appears to work (even though it would be better described as %5.1f), but try that in a table and you'll find that the column won't line up when another value is just 1.23 for instance.

For illustration, printf("%3.2f\n",\$_) for (3.2,32.2,322.2) gives:

```3.20
32.20
322.20

while printf("%6.2f\n",\$_) for (3.2,32.2,322.2) gives:

```  3.20
32.20
322.20

--
I'd like to be able to assign to an luser

Thanks buddy for this, I will have it rectified, when I saw the start of your reply and I was like aoooo I mixed up some other coordinates system from another utility. Thanks, I admit I fell for the trap, I will make an update.
Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind
by poolpi (Hermit) on Jul 20, 2009 at 06:57 UTC

May be of interest ;)

```#!/usr/bin/perl
use strict;
use warnings;
use Math::BigFloat;

my \$base = Math::BigFloat->new(q{895.3});
my \$incr = Math::BigFloat->new(q{0.01});

while ( \$base->bcmp(900) ) {
print \$base->bstr(), "\n";