John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

You know what pack "N" does for ints? I want to do that for BigInts. There is nothing in the interface that makes this especially simple, even though it ought to be efficient since many times the internal representation will be this way. Converting to a binary string of character '1' and '0' and then repacking that seems inelegant and bloated.

Any suggestions on different ways I might do it, if not a Very Fine way to do it?

—John

2005-03-11 Edited by Arunbear: Changed title from 'encoding BitInts: TIMTOWTDI but any good way?'

  • Comment on encoding BigInts: TIMTOWTDI but any good way?

Replies are listed 'Best First'.
Re: encoding BigInts: TIMTOWTDI but any good way?
by kvale (Monsignor) on Mar 11, 2005 at 18:49 UTC
    I agree that an ascii representation of a base 2 bigint is especially inefficient :)

    Sine there is no machine native representation of a bigint that has an analog of a portable network order, why not use good old ascii? To make it more efficient, use a decimal or hexadecimal base (from the manpage):

    # conversion to string (do not modify their argument) $x->bstr(); # normalized string $x->as_hex(); # as signed hexadecimal string with prefixed 0 +x # Number creation $x = Math::BigInt->new($str); # defaults to 0
    One could get double density with packed hexadecimals, but it would not be as human readable.

    -Mark

Re: encoding BigInts: TIMTOWTDI but any good way?
by Roy Johnson (Monsignor) on Mar 11, 2005 at 18:43 UTC
    You should be able to output as_hex, break it into number-sized pieces and pack those. Not sure that's more elegant than going to a binary string. Maybe a little less bloated.

    What exactly do you want to do with the encoded critters?


    Caution: Contents may have been coded under pressure.
Re: encoding BigInts: TIMTOWTDI but any good way?
by ikegami (Patriarch) on Mar 11, 2005 at 19:15 UTC

    One way:

    use Math::BigInt; $x = Math::BigInt->new(5000000000); print($x->as_hex(), $/); die("This doesn't work on negative numbers.\n") if $x->is_neg(); my $packed = ''; while (!$x->is_zero()) { $y = $x->copy()->bmod(256); $packed = pack('C', $y) . $packed; $x->brsft(8); } print('0x', unpack('H*', $packed), $/); # Verify work.

    Since you're packing, you're probably expecting a fixed size result. If so, this can be modified to handle negative numbers and to return a fixed size result.

Re: encoding BigInts: TIMTOWTDI but any good way?
by belg4mit (Prior) on Mar 12, 2005 at 12:08 UTC