Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

This is probably a newbie-ish question, but I can't really find the answer anywhere in the docs... So here goes: consider this piece of code:

$a = 3000000000000011;
print "a: $a";

If you run it, you get the following output:

a: 3.00000000000001e+15

Now I'm not sure if this is a bug or a feature, but 3.00000000000001e+15 is what you get not only if you print it, but also when you try to insert it into a SQL table. And as my experience shows, Sybase is not very happy with this loss of precision, especially in a foreign key field. So is there any pragma, or some other way to tell perl not to do any funny things to your floats ? I found that saying $a = sprintf("%.0f",3000000000000011) solves the problem, but surely there must be a more elegant solution available...

Replies are listed 'Best First'.
Re: Handling large numbers
by Brovnik (Hermit) on Jun 06, 2001 at 01:38 UTC
    Assuming you do want to do some calculations, Math::BigInt is for you.
    use Math::BigInt; $a = Math::BigInt->new("3000000000000011"); $b = Math::BigInt->new("1233456789012345"); $a += $b; print "a: $a\n";
    results in :
    a: +4233456789012356

    --
    Brovnik
Re: Handling large numbers
by no_slogan (Deacon) on Jun 06, 2001 at 01:34 UTC
    If you don't need to do any number-crunching on $a, why not use this:
    $a = "3000000000000011";

    Floating point numbers are imprecise. There are only so many digits of precision available, so you can't expect perl to be able to preserve the last "1" if you do something like this...
    print 1000000000000000000000000000001

      I thought floating point numbers were the computer form of real numbers,
      ie. they have a decimal point
      but 1000000000000000000000000000001 is an integer.

      "Argument is futile - you will be ignorralated!"

        Numbers are always floating-point in perl. Usually. True, you can use integer, but that doesn't seem to take effect until after the parser has chewed the number up and spat it out as a float. On many platforms, 1000000000000000000000000000001 is too big a number to represent as an integer, anyway. Integers have some implementation-dependent maximum number of bits. Computer arithmetic is not the same as mathematical arithmetic. There's always some limit on the size (number of digits) of a number the computer can remember, even if it's the machine's entire virtual memory area.
Re: Handling large numbers
by petdance (Parson) on Jun 06, 2001 at 01:40 UTC
    If you're using them as foreign keys, then it sounds to me that you're not working with numbers, but rather with strings that happen to made entirely of digits.

    In general, if you're not doing any computation, then don't use numeric values. Do everything with strings.

    xoxo,
    Andy

    %_=split/;/,".;;n;u;e;ot;t;her;c; ".   #   Andy Lester
    'Perl ;@; a;a;j;m;er;y;t;p;n;d;s;o;'.  #   http://petdance.com
    "hack";print map delete$_{$_},split//,q<   andy@petdance.com   >
    
Re: Handling large numbers
by VSarkiss (Monsignor) on Jun 06, 2001 at 06:07 UTC
    As others have mentioned, Math::BigInt would do the trick, if you're doing everything in Perl. However, you've also used the words "SQL" and "Sybase" in your note, which makes me think otherwise....

    Before anyone can render any kind of answer, you need to provide more information:

    • What is the type of the column you're trying to write into? If it's a Sybase database, are you using float, decimal (a.k.a. numeric) or (shudder) money?
    • How are you talking to the database? Are you using DBI or Sybase::CTlib? They're both by the same author, Michael Peppler, but there are differences.
    • When you say "Sybase isn't happy", what do you mean? Are you getting a loss-of-precision error, or do you think you're losing precision because when you query later, the value in the column doesn't look like what you think you wrote?
    As you can see, there's a lot of variability possible. I'd be glad to help -- I work with Perl and Sybase on a daily basis -- but I really don't have enough to go on....
Re: Handling large numbers
by mpeppler (Vicar) on Oct 03, 2001 at 03:29 UTC
    I'm assuming that the target field is a numeric() value with a fairly large precision.

    If you use Sybase::CTlib you can use the newnumeric() call to create a numeric value in memory (similar to Math::BigInt, I think), and then pass that value in to get it inserted.

    Objects of type Sybase::CTlib::Numeric() use operator overloading, so you can use the normal arithmetic operations on them and the appropriate cs_calc() calls will be used internally.

    Michael

Re: Handling large numbers
by srawls (Friar) on Jun 06, 2001 at 01:27 UTC
    I don't no too much about this module, but I believe that Math::BigInt could do the trick.

    The 15 year old, freshman programmer,
    Stephen Rawls
Re: Handling large numbers
by Zaxo (Archbishop) on Jun 06, 2001 at 01:38 UTC

    You overflow int if you force it:

    $ perl -e '$c=3000000000000011|0;print "$c\n"' 4294967295

    and fp epsilon drowns the last digit you want, so:

    use Math::BigInt $c = Math::BigInt->new('3000000000000011'); print "$c\n";

    After Compline,
    Zaxo