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...
Footnotes:
| [reply] |
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.
| [reply] |
| [reply] |
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
See also PerlFAQ4 - Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?
Update: Added example code
Update^2: Eventually found the FAQ | [reply] [d/l] |
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
| [reply] [d/l] |
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
| [reply] [d/l] [select] |
| [reply] [d/l] |
#!/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";
$base->badd($incr);
}
hth, PooLpi
| [reply] [d/l] |