Hack #99. Track Your Approximations
Avoid rounding errors; get the right results.
Floating-point numbers are inherently approximate. Perl represents numbers in the most accurate way it can on your hardware, but typically it can't do better than about 16 significant digits. That means that a calculation you think is accurate:
my $dx = 21123059652674105965267410596526741059652674100000000; my $rate = 1.23e12; my $end = ( 23 * $dx - $rate * 230 - 2.34562516 ** 2 - 0.5 ) ** 0.33;
may in fact not be precise.
On a 32-bit machine, the various floating-point approximations introduced along the way may mean the final value of $end
is inaccurate by about 937. Of course, the correct value of $end
is approximately 520642400412471062.6461124479995125761153. If $end
is your annual profit margin, you may not really care if it's off by a thousand dollars or so. On the other hand, if the same calculation were a trajectory for a lunar lander, turning off the retro-rockets 937 meters too high might matter a great deal.
How can you make sure your calculations aren't fatally inaccurate? The easiest way is to let Perl do it for you. To accomplish that, you need to change the way floating-point numbers work. Easy.
Interval interlude
Interval arithmetic is a simple technique for tracking the accuracy of numeric computations. Instead of representing each value as a single number, encode it as a range: minimum possible value to maximum possible value.
For example, most platforms can't represent the number 1.2345678901234567890 ...
Get Perl Hacks now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.