extract number from binary string

Discussion in 'Perl Misc' started by Looden, Mar 1, 2010.

  1. Looden

    Looden Guest

    Hi
    I'm parsing a binary string, which encodes a number.
    I don't know the length of the string in advance: 1, 2, 3 or 4 bytes.
    The bytes of the string are in network order.
    How can I retrieve the number?

    I've written this sub, there must be a better way:

    sub parse_number {
    my $arg = shift;
    my $size = length($arg);
    my $value = 0;
    my $buf;
    for (my $i=($size-1);$i>=0;$i--){
    $buf = unpack "C", (substr $arg, $i, 1);
    $value += $buf * (256**($size-$i-1));
    }
    return $value;
    }

    Note: If the length of the string was always 2 bytes, I could just do:
    sub parse_n { return unpack "n", shift; }

    Thanks in advance.
     
    Looden, Mar 1, 2010
    #1
    1. Advertising

  2. Looden

    Uri Guttman Guest

    >>>>> "L" == Looden <> writes:

    L> I'm parsing a binary string, which encodes a number. I don't know
    L> the length of the string in advance: 1, 2, 3 or 4 bytes. The bytes
    L> of the string are in network order. How can I retrieve the number?

    L> sub parse_number {
    L> my $arg = shift;

    pick a better name for that. $arg is generic.

    L> my $size = length($arg);
    L> my $value = 0;
    L> my $buf;
    L> for (my $i=($size-1);$i>=0;$i--){
    L> $buf = unpack "C", (substr $arg, $i, 1);
    L> $value += $buf * (256**($size-$i-1));
    L> }
    L> return $value;
    L> }


    much simpler would be to unpack the bytes to an array and then do the
    multiply/add stuff in a loop. untested and unfinished:

    my @bytes = unpack 'C*, $byte_string ;

    my $value ;
    for my $byte ( @bytes ) {

    multiply/add code
    }

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Mar 1, 2010
    #2
    1. Advertising

  3. Looden wrote:
    > Hi
    > I'm parsing a binary string, which encodes a number.
    > I don't know the length of the string in advance: 1, 2, 3 or 4 bytes.
    > The bytes of the string are in network order.
    > How can I retrieve the number?
    >
    > I've written this sub, there must be a better way:
    >
    > sub parse_number {
    > my $arg = shift;
    > my $size = length($arg);
    > my $value = 0;
    > my $buf;
    > for (my $i=($size-1);$i>=0;$i--){
    > $buf = unpack "C", (substr $arg, $i, 1);
    > $value += $buf * (256**($size-$i-1));
    > }
    > return $value;
    > }
    >
    > Note: If the length of the string was always 2 bytes, I could just do:
    > sub parse_n { return unpack "n", shift; }


    $ perl -le'
    my @strings = ( "\xa", "\xb\x1", "\xc\x2\x3", "\xd\x4\x5\x6" );
    for my $string ( @strings ) {
    my $number = substr "\0\0\0" . $string, -4;
    print unpack "N", $number;
    }
    '
    10
    2817
    786947
    218367238



    John
    --
    The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway
     
    John W. Krahn, Mar 1, 2010
    #3
  4. Looden

    Oscar Almer Guest

    On Mon, 01 Mar 2010 19:17:54 +0100
    Looden <> wrote:

    > Hi
    > I'm parsing a binary string, which encodes a number.
    > I don't know the length of the string in advance: 1, 2, 3 or 4 bytes.
    > The bytes of the string are in network order.
    > How can I retrieve the number?
    >
    > I've written this sub, there must be a better way:
    >
    > sub parse_number {
    > my $arg = shift;
    > my $size = length($arg);
    > my $value = 0;
    > my $buf;
    > for (my $i=($size-1);$i>=0;$i--){
    > $buf = unpack "C", (substr $arg, $i, 1);
    > $value += $buf * (256**($size-$i-1));
    > }
    > return $value;
    > }
    >
    > Note: If the length of the string was always 2 bytes, I could just
    > do: sub parse_n { return unpack "n", shift; }
    >
    > Thanks in advance.
    >


    I seem to recall (I wrote some code that parses binary strings recently)
    that oct() does that, if you prefix it with "0b" to indicate
    binaryness. Some application of reverse / substr might be useful to
    handle byte ordering.

    I could be wrong.

    //Oscar
     
    Oscar Almer, Mar 1, 2010
    #4
  5. Looden

    Uri Guttman Guest

    >>>>> "OA" == Oscar Almer <> writes:

    OA> I seem to recall (I wrote some code that parses binary strings
    OA> recently) that oct() does that, if you prefix it with "0b" to
    OA> indicate binaryness. Some application of reverse / substr might be
    OA> useful to handle byte ordering.

    OA> I could be wrong.

    you are wrong. :)

    she has real binary bytes. 0b deals with bits in ascii form.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Mar 1, 2010
    #5
  6. Looden

    Oscar Almer Guest

    On Mon, 01 Mar 2010 13:47:35 -0500
    "Uri Guttman" <> wrote:


    > OA> I could be wrong.
    >
    > you are wrong. :)
    >
    > she has real binary bytes. 0b deals with bits in ascii form.
    >
    > uri
    >


    Ah, My bad.

    I apologize and retract the previous.

    //Oscar
     
    Oscar Almer, Mar 1, 2010
    #6
  7. Looden

    Guest

    On Mon, 01 Mar 2010 19:17:54 +0100, Looden <> wrote:

    >Hi
    >I'm parsing a binary string, which encodes a number.
    >I don't know the length of the string in advance: 1, 2, 3 or 4 bytes.
    >The bytes of the string are in network order.
    >How can I retrieve the number?
    >
    >I've written this sub, there must be a better way:
    >
    >sub parse_number {
    > my $arg = shift;
    > my $size = length($arg);
    > my $value = 0;
    > my $buf;
    > for (my $i=($size-1);$i>=0;$i--){
    > $buf = unpack "C", (substr $arg, $i, 1);
    > $value += $buf * (256**($size-$i-1));
    > }
    > return $value;
    > }
    >
    >Note: If the length of the string was always 2 bytes, I could just do:
    >sub parse_n { return unpack "n", shift; }
    >
    >Thanks in advance.


    I guess you could also do:

    sub parse_number {
    my $arg = shift;
    vec("\0"x(4-length $arg).$arg, 0, 32);
    }

    -sln
     
    , Mar 1, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. makok
    Replies:
    1
    Views:
    6,776
    Anders Hellerup Madsen
    Feb 23, 2004
  2. Horacius ReX
    Replies:
    4
    Views:
    314
    Sion Arrowsmith
    Dec 21, 2007
  3. Jochen Brenzlinger
    Replies:
    5
    Views:
    691
    Daniel Pitts
    Nov 21, 2011
  4. Jim
    Replies:
    6
    Views:
    735
  5. Adam

    Extract a number from a string.

    Adam, Nov 8, 2004, in forum: Perl Misc
    Replies:
    10
    Views:
    166
    Ben Morrow
    Nov 11, 2004
Loading...

Share This Page