Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

64 bit Integer anyone?

by dedwards25 (Initiate)
on Oct 11, 2000 at 23:34 UTC ( [id://36298]=perlquestion: print w/replies, xml ) Need Help??

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

I have a binary file that contains a 64 bit Integer field. I want to get use this value in a Perl program. Normally I use unpack to translate binary file data into perl variables, but can't figure out how to do this conversion. Can anyone help me out? Are there any CPAN modules that help with this?

Replies are listed 'Best First'.
(tye)Re: 64 bit Integer anyone?
by tye (Sage) on Oct 12, 2000 at 00:46 UTC

    The "q" format for pack()/unpack() is only supported if your copy of perl was compiled with quadword support (only available on some platforms).

    But just about any version of Perl supports 53-bit integers which is often plenty, even when dealing with 64-bit data.

    #!/usr/bin/perl -wl use strict; my $little; BEGIN { $little= unpack "C", pack "S", 1; } sub quad { my( $str )= @_; my $big; if( ! eval { $big= unpack( "Q", $str ); 1; } ) { my( $lo, $hi )= unpack "LL", $str; ( $hi, $lo )= ( $lo, $hi ) if ! $little; $big= $lo + $hi*( 1 + ~0 ); if( $big+1 == $big ) { warn "Forced to approximate!\n"; } } return $big; } my @quads= ( "\xff\xff\xff\xff\xff\xff\xff\xff", "\x00\x3f\xff\xff\xff\xff\xff\xff", "\x00\x1f\xff\xff\xff\xff\xff\xff" ); if( $little ) { for( @quads ) { $_= reverse $_; } } for( @quads ) { print quad( $_ ); } __END__ This prints: Forced to approximate! 1.84467440737096e+019 Forced to approximate! 1.8014398509482e+016 9.00719925474099e+015

    Note that assumes an unsigned 64-bit integer.

            - tye (but my friends call me "Tye")

      Okay, I think I have signed quads working...

      #!/usr/bin/perl -w use strict; my $little; BEGIN { $little= unpack "C", pack "S", 1; } sub quad { my( $str )= @_; my $big; if( ! eval { $big= unpack( "Q", $str ); 1; } ) { my( $lo, $hi )= unpack "LL", $str; ( $hi, $lo )= ( $lo, $hi ) if ! $little; $big= $lo + $hi*( 1 + ~0 ); if( $big+1 == $big ) { warn "Forced to approximate!\n"; } } return $big; } sub squad { my( $str )= @_; my $big; if( ! eval { $big= unpack( "Q", $str ); 1; } ) { my( $lo, $hi )= unpack $little ? "Ll" : "lL", $str; ( $hi, $lo )= ( $lo, $hi ) if ! $little; if( $hi < 0 ) { $hi= ~$hi; $lo= ~$lo; $big= -1 -$lo - $hi*( 1 + ~0 ); } else { $big= $lo + $hi*( 1 + ~0 ); } if( $big+1 == $big ) { warn "Forced to approximate!\n"; } } return $big; } my @quads= ( "\xff\xff\xff\xff\xff\xff\xff\xff", "\x00\x3f\xed\xcb\xa9\x87\x65\x43", "\x00\x1f\xff\xff\xff\xff\xff\xff" ); if( $little ) { for( @quads ) { $_= reverse $_; } } $|= 1; push @quads, ~$quads[1], ~$quads[2]; for( @quads ) { print quad( $_ ), "\n"; print squad( $_ ), "\n\n"; } if( quad($quads[2]) == -1 - squad($quads[4]) ) { print "two's complement works!\n"; } __END__ This prints: Forced to approximate! 1.84467440737096e+019 -1 Forced to approximate! 1.79943825111381e+016 Forced to approximate! 1.79943825111381e+016 9.00719925474099e+015 9.00719925474099e+015 Forced to approximate! 1.84287496911984e+019 Forced to approximate! -1.79943825111381e+016 Forced to approximate! 1.84377368744548e+019 -9.00719925474099e+015 two's complement works!

      Though, squad() seems overly convoluted. Improvements welcome.

              - tye (but my friends call me "Tye")
(jcwren) Re: 64 bit Integer anyone?
by jcwren (Prior) on Oct 11, 2000 at 23:39 UTC
    Pack/unpack support the 'q' and 'Q' types for 64 bit signed and unsigned quads.

    See "perldoc -f pack" and "perldoc -f unpack" for how pack and unpack are used.

    I imagine the easist way would be to slurp the binary data into a string, and unpack it as you go. As you pull parts of the string off, you can then discard that portion on the string. If you can post a example of what the data stream looks like, someone here will probably post some example code for doing this.

    If you need to manipulate 64 bits integers (particularly multiply them), see Math::BigInt will allow arbitrary sized integers.

    --Chris

    e-mail jcwren

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://36298]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2024-04-26 08:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found