[Wellington-pm] numeric types

Daniel Pittman daniel at rimspace.net
Mon Oct 27 04:08:06 PDT 2008


Richard Hector <richard at walnut.gen.nz> writes:
> On Mon, 2008-10-27 at 15:26 +1100, Daniel Pittman wrote:

[...]

>> Specifically, see bigrat(3perl) for the easy path, or Math::BigRat for
>> the library that uses if you want to do it the hard way.[1]
>
> That looks like it might be a nice way to store numbers, but I still
> have the issue of how to get them out of the DB and into one of those
> without converting to a float along the way.

bigrat overloads a whole bunch of stuff to magically use Math::BigRat
objects where appropriate -- since this is global, not limited to your
own module, this can transparently add rational number support outside
your namespace.

>> > I'm not even clear that that's what will happen; it seems difficult
>> > to work out how Perl has actually stored a given value; perhaps DBI
>> > returns it as a string, which I can match and stick into a more
>> > complex data structure that preserves the components?
>> 
>> You can use Data::Dumper, or one of the non-bundled methods, to probe
>> what data type it is -- but, generally, it is fairly mutable.
>
> This is the core of my question, I think. I've done a few tests, and
> Data::Dumper doesn't seem to display scalars any differently based on
> their storage, as far as I can see.  What are these 'non-bundled
> methods' you're talking about?

Devel::Peek, predominantly, which gives a lot of information about the
internals of the object.[1]  Possibly something like Devel::XRay to inspect
code flow, but I don't think that helps a lot.

Mostly, though, I would expect that you could find out most of what you
want (is this a rational or a float) using ref, which will return the
class of the rational, or '' for a normal float or int.

[...]

>> Hard work and enthusiasm.  You can probably derive appropriate black-box
>> testing from this: http://speleotrove.com/decimal/decifaq1.html#inexact
>
> Test by doing calculations and seeing what I get? I can see that that
> could work, but I suspect conversions could happen in multiple places,
> leading to ambiguity of my results.

Well, my expectation would be that you would inspect the DBD::Pg code,
and/or tested this, to determine what it returns.

The quick answer is: DBD::Pg, in the absence of any configuration,
returns values from a NUMERIC(10,2) column as strings, which you can
then convert to a Math::BigRat trivially, giving you the precision you
want.

[...]

> Andrew: whether I actually need this is a separate issue, of course
> ...  but that speleotrove link gives examples of these issues showing
> up in funny places.

*nod*  Personally, I think the cost of manually wrapping the column to a
Math::BigRat, or configuring your ORM to do so, is pretty low -- but
then you have to deal with getting that data back into PGSQL. :/

> I'm tempted to just store everything as pairs (numerator and
> denominator) of integers. Seems much more precise than what SQL's
> numeric type can offer.

The biggest advantage of using NUMERIC or DECIMAL is that you can use
the database safely to act on the data: SUM(numeric_column) works
correctly[2], where it wouldn't with something you wrote yourself.

If you treat the database as a storage system only, rather than doing
any calculation or comparison in it, then this might be fine...

> And if I can't get those numeric numbers in and out of perl easily,
> then perhaps less work as well.

They go in quite fine.  Back out is more difficult, because Math::BigRat
wants to output decimal and PGSql doesn't like that syntax by default
for numeric columns...

Regards,
        Daniel

Footnotes: 
[1]  Which, apparently, is a built-in module in 5.8.8, which says that
     I am getting forgetful in my old age.

[2]  As in, preserves accuracy.



More information about the Wellington-pm mailing list