in reply to Rounding Errors
Well I checked it out and ended up writing a tutorial for you..
Here's what I did when you asked that question:
Look up http://search.cpan.org
Search for Math::BigFloat
Click on "Math::BigFloat" as it appears under Perl5.005_03
Realize it must already be installed on my system!
So at command line I typed man "Math::BigFloat" for the manual.
You probably got this far, but it is a bit terse
(read "cryptic").
If you don't have a Unix command line in front of you, check
out the manual page which shows up at the above link:
http://search.cpan.org/doc/GBARR/perl5.005_03/lib/Math/BigFloat.pm
There is a little longer manual page for the version of the library
provided with perl 5.7, which I don't have but here's the link
(it showed up in the search results above):
http://search.cpan.org/doc/JHI/perl-5.7.0/lib/Math/BigFloat.pm
This library is object oriented, meaning that it lets you create
an object which represents a long floating point number, and then
perform operations on such objects. It also transforms ("overloads")
common arithmetic operators so that you can have fun and appear to
multiply and divide really huge number objects together by just typing
a multiplication or division sign. Overloading is quick and fun but it is
sometimes hard to debug, and may not give you access to subtle points
in functionality of the library.
The Synopsis section shows the "use" line you need to load the library,
and a sample line which shows you how to create a bigfloat object.
By picking a variable name and setting it to the output of the
library's "new" command you can generate a new bigfloat object based on
a long floating point number which you provide as a string, in quotes.
You could append a number of strings together to make a longer one if you like.
Since Perl uses the same type (scalar) variable for strings and numbers,
you can mix them together. Either of these following two ways of stating it
would create a bigfloat object (technically, an "instance" of the object) for you:
$alongstring = "143208.13420789709814309781432"; # just some random keystrokes
$hisfloat = Math::BigFloat->new($alongstring);
$herfloat = new Math::BigFloat($alongstring);
You can also leave out the parentheses, as the documentation does.
The "new" method (think subroutine) is special in that you can type it in advance
so it sounds like English. But normally an arrow is used when you want to access
a method which belongs to a certain instance of an object. Since $hisfloat and
$herfloat inherit the methods defined in the library, such as "fmul" and "fdiv".
Here is the same thing first calling methods, then using the overloading provided
by the library. I guessed that NSTR in the documentation means "any number string
or a bigfloat object". Usually overloading just works with objects, but it is
even looser than that in this library (which can be dangerous, see below).
print $hisfloat->fmul($herfloat);
print $hisfloat * $herfloat;
Here is a test you can do on the command line (all on one line):
perl -e 'use Math::BigFloat; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f * $g * 3.14159 , "\n";'
605472261221004971587.2079631921116943252504708191763655250636246607274730865378109
The library seems to add engineering notation when you call by method instead of using overloaded arithmetic operators (no loss of precision):
perl -e 'use Math::BigFloat; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f->fmul($g * 3.14159) , "\n";'
+6054722612210049715872079631921116943252504708191763655250636246607274730865378109E-61
But truncates it to normal short floating point length, when you put a bare number outside the parentheses:
perl -e 'use Math::BigFloat; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f->fmul($g) * 3.14159 , "\n";'
6.05472261221005e+20
Which I fixed by keeping everything a BigFloat object:
perl -e 'use Math::BigFloat; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f->fmul($g) * (new Math::BigFloat("3.14159")) , "\n";'
605472261221004971587.2079631921116943252504708191763655250636246607274730865378109
I can't tell if this is flakiness or proper functioning, since the docs do say that it is a development version I am using.
I recommend that you do everything in a program, one operation per line, and only
explicit method calls, not operator overloading, to ensure debuggable, consistent results.
You can also look at the module code itself for hints as to what is going on..
try "locate BigFloat.pm" on your system. You will note that unless you explicitly
specify scale, $div_scale is 40 in the code which means you get only 40 digits of
accuracy in that case.
Here is an example of the difference which global settings for your library will have. Instead of div_scale (which can be set on a per-instance basis anyway) I am looking at trunc:
perl -e 'use Math::BigFloat; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f->fdiv($g) , "\nmode: "
+107175520718176952100999428361427933683486722E-50
mode: even
perl -e 'use Math::BigFloat; $Math::BigFloat::rnd_mode = "trunc"; $s="14372098.1320498713209847102398471"; $f = new Math::BigFloat($s); $g = Math::BigFloat->new("13409870123087.1329481723049817230498712304981"); print $f->fdiv($g) , "\nmode: ", $Math::BigFloat::rnd_mode, "\n";'
+1071755207181769521009994283614279336834867219E-51
mode: trunc
Well that was fun, back to work for me.. Hope this helps.
Matt
Re: Rounding Errors
by Anonymous Monk on Jan 11, 2001 at 05:32 UTC
|
Thanks ever so much for all your help. With the information you gave me I was able to get the science fair report done on time today and I learned a lot that I didn't know before. I appreciate each of you taking the time to explain it to me. That tutorial especially helped, as I didn't understand what many of those terms (like overloading) meant until you explained them. Thank you! | [reply] |