Phoenix.pm: Math

Scott Walters phaedrus at contactdesigns.com
Thu Aug 2 13:46:30 CDT 2001


Tom,

Hmm. I'm having a thought there. Tony has the right idea - if you
have enough precision with Perl internal math, but you're worried
about acculating an error from repeated dec->bin->dec translation,
why not overload the * and / and % operators, and add a truncation-
rounding stage? This should be nearly as fast, as strings of binary
data aren't being unpacked into an array at every operation, even
though as Rob says overload has some overhead.

My other thought is to see if your processor has a BCD (binary coded
decimal) mode, and use Inline C with some inline assembler =)

package StupidFloat;
use Exporter;
@EXPORT = qw(stupidfloat);

sub stupidfloat {
  my $nombre = shift;
  my $value = 0.0;
  (my $callerpackage) = caller;
  *{$callerpackage.'::'.$nombre} = sub () : lvalue {
    $value = substr($value, 0, 14);
  };
}

package Work;
# use StupidFloat; # have to write a bloomin file for this to work
StupidFloat::stupidfloat result;
result() = (0.07 * 10000.0);
printf "%40.35f\n", result();

Well, that wasn't quite what I expected. Turns out overloading
operators is quite tricky, and only works when the variables the
operators are operating on are objects. Makes a kinda OO sense,
but then the variables don't work with normal operators, since
they are then references... 
So  I redid it with lambdas. I thought the sub : lvalue {} and
the the sub () {}  magic would work together (so that it would
work in bareword form and then return an lvalue), but it didn't.
Actually, on second thought, it's prolly just that it didnt
appear with the correct name in the correct scope, since 
sub () { } is only a hint to the compiler..... ahh well.
So, basicly, this works, but the "variable" you create, you
have to tack ()'s onto the end or & in the front like a bloody 
function. In tyhe substr() call you can specify how many decimal
degits of precesion you want to keep. It looks like its doing
14 but thats just a quick guess.

-scott



  

On Wed, 1 Aug 2001, Thomas Whitney wrote:

> I am parsing mathematical models where there are LONG expressions of various
> precessions, nothing too extreme. The error showed up when doing a ceiling
> function. I could us sprintf in my ceiling function to fix it and use perls
> math, but the error makes me a bit nervous, and considering the mathematical
> nature of the project, it probably isn't a good idea anyway. Using Math:BigFloat
> at least doubles the time. I saw a few modules on cpan that looked like they
> might work, but I have a have the sysadmin install them for me.
> 
> Thanks
> Tom
> 
> EdelSys Consulting wrote:
> 
> > Why not just use sprintf to round?  What kind of precision we
> > talking about here?
> >
> > "Throw me a frickin' bone here, Scott"
> >
> >   -- Doctor Evil
> >
> > At 04:43 PM 8/1/01 -0500, you wrote:
> > >Tom;
> > >     Your code is fine - the problem is just that numbers (floating point
> > or otherwise) are stored in internal (binary) representation. The "extra
> > digits" that you see tacked on the end are a consequence of how a floating
> > point number is stored in binary format. The inconsistencies are compounded
> > when you perform arithmetic operations. If you really need long floats, use
> > Math::BigFloat. If it's precision you're worried about, check out
> > Math::FixedPrecision. Both will be slow (compared to "straight math
> > operations") due to overloading of arithmetic operators. Hope this helps.
> > >                         - Rob
> > >
> > >-----Original Message-----
> > >From: Thomas Whitney [mailto:whitneyt at agcs.com]
> > >Sent: Wednesday, August 01, 2001 2:16 PM
> > >To: phoenix-pm-list at happyfunball.pm.org
> > >Subject: Re: Phoenix.pm: Math
> > >
> > >
> > >Thanks Scott,
> > >
> > >Here is the problem I was having last year. Just ran it again same
> > problem. I am running on v5.6.0. I don't see anything wrong that I am doing.
> > >
> > >Script started on Thu Aug 17 15:57:29 2000
> > >peoblej at holodeck[148]: cat bug.pl
> > >#!/usr/local/bin/perl -w
> > >use strict;
> > >
> > >my $result = 0.0;
> > >$result = 0.07 * 10000.0;
> > >printf "%40.35f\n", $result;
> > >peoblej at holodeck[149]: bug.pl
> > > 700.00000000000011368683772161602973938
> > >peoblej at holodeck[150]: exit
> > >script done on Thu Aug 17 15:57:44 2000
> > >
> > >Thanks
> > >Tom
> > >
> > >Scott Walters wrote:
> > >
> > >> Hey Tom,
> > >>
> > >> Well, looking at Math::BigInt/BigFloat, they do everything in Perl by
> > >> unpacking into an array from a string... something in C or Perl
> > >> that minipulated it directly in its binary format would be much faster...
> > >> what problems were you having with perls built in operators? Overflow?
> > >> Precision? Don't know of anything offhand, and I assume you've searched
> > >> CPAN... If you wanted to use a C library, Doug just did a demo on
> > >> [what was that?] Embed, which makes it really easy to stick some C
> > >> right in middle of your Perl.
> > >>
> > >> -scott
> > >>
> > >> On Wed, 1 Aug 2001, Thomas Whitney wrote:
> > >>
> > >> > Hi All,
> > >> >
> > >> > I am doing a lot of decimal arithmetic. I ran into problems using
> > perl's standard arithmetic. Right now I am using Math::BigFloat, but it
> > seems slow. Can anybody recommend a better module
> > >> >
> > >> > Thanks
> > >> > Tom
> > >> >
> > >> >
> > >
> > >
> 
> 




More information about the Phoenix-pm mailing list