Perl function for negative integers using the 2's complement in hex?

Discussion in 'Perl Misc' started by stylechief, Apr 8, 2005.

  1. stylechief

    stylechief Guest

    I cannot seem to find a Perl function that will return the 2's
    complement of a negative integer represented in hex.
    For example:
    ffbe8e should return -16754, not 16760462

    hex() works fine for positive integers but not here
    pack/unpack don't seem to want to produce anything negative (just 0)

    I imagine that there is a 'brute force' method, but it seems that there
    should be an eloquent function that speaks in 2's complement . . . .

    Thanks,
    Liam
    stylechief, Apr 8, 2005
    #1
    1. Advertising

  2. stylechief

    Joe Smith Guest

    Re: Perl function for negative integers using the 2's complementin hex?

    stylechief wrote:
    > I cannot seem to find a Perl function that will return the 2's
    > complement of a negative integer represented in hex.
    > For example:
    > ffbe8e should return -16754, not 16760462


    You have to remember that 32-bit integers are represented by
    eight hex digits, not six.

    linux% perl -le 'printf "%d %d\n",0xffbe8e,0xffffbe8e'
    16760462 -16754

    If you have a 24-bit number you will need to sign-extend the
    most significant bit in order to produce a 32-bit number.

    linux% cat temp
    $bits_24 = hex("ffbe8e");
    $bits_32 = $bits_24 | (($bits_24 & 0x800000) ? 0xff000000 : 0);
    printf "%d %.0f\n", $bits_32, $bits_32;

    linux% perl temp
    -16754 4294950542
    Joe Smith, Apr 8, 2005
    #2
    1. Advertising

  3. stylechief

    stylechief Guest

    Thanks for the help, guys. It is a 24 bit number I'm working with.
    stylechief, Apr 8, 2005
    #3
  4. stylechief

    stylechief Guest

    That works like a charm when one can explicitly pass a hex number like
    the above example. However, for whatever reason, when one attempts to
    read from a binary file and use unpack() to deliver the hex numbers,
    one gets:
    Argument "ffbe8e" isn't numeric in pack at E:\Test\bif.plx line 5.

    code:
    open (BINARYFILE, "<000332") || die "Cant open: $!\n";
    while(read(BINARYFILE, $data, 3)){
    $data= unpack 'H*',$data;
    print unpack 'i',pack 'i',$data;
    print "\n";
    }
    close (BINARYFILE) || die"Cant close: $!\n";

    It *is* unpacking to a 24 bit hex number, but fails to see this number
    as numeric. It gets "stringified" somehow.
    stylechief, Apr 12, 2005
    #4
  5. stylechief <> wrote:

    > That works like a charm



    What does?


    > when one can explicitly pass a hex number like
    > the above example.



    What example above?


    Please compose followups the normal way and quote some context.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Apr 12, 2005
    #5
  6. stylechief

    Joe Smith Guest

    Re: Perl function for negative integers using the 2's complementin hex?

    stylechief wrote:
    > That works like a charm when one can explicitly pass a hex number like
    > the above example. However, for whatever reason, when one attempts to
    > read from a binary file and use unpack() to deliver the hex numbers,
    > one gets:
    > Argument "ffbe8e" isn't numeric in pack at E:\Test\bif.plx line 5.
    >
    > code:
    > open (BINARYFILE, "<000332") || die "Cant open: $!\n";
    > while(read(BINARYFILE, $data, 3)){
    > $data= unpack 'H*',$data;
    > print unpack 'i',pack 'i',$data;
    > print "\n";
    > }
    > close (BINARYFILE) || die"Cant close: $!\n";
    >
    > It *is* unpacking to a 24 bit hex number,



    No, it is unpacking to a six-character string of hexadecimal digits.
    The phrase "24 bit hex number" is meaningless, what you've got is
    a 24-bit number expressed as a string of hexadecimal digits.

    > but fails to see this number as numeric. It gets "stringified" somehow.


    Using 'H' with unpack() returns a string, not a number.
    The string of hexadecimal digits needs to go through the hex() function
    in order to be numeric.

    $hexdata = unpack 'H*',$data;
    $integer = hex $hexdata;
    print unpack 'i', pack 'i',$integer;

    or

    read(BINARYFILE, $three_bytes, 3);
    $four_bytes = '\x00' . $three_bytes;
    $integer = unpack 'i',$four_bytes;

    or

    $sign_extend = ($three_bytes & "\x80\x00\x00") ? "\xff" : "\x00";
    $four_bytes = $sign_extend . $three_bytes;

    (Obviously, little-endian machines and big-endian ones need to
    handle those last two differently.)

    -Joe
    Joe Smith, Apr 12, 2005
    #6
  7. stylechief

    stylechief Guest

    Thanks to all for your time and consideration. The solution that I was
    seeking:

    open (BINFILE, "<000332") || die "Cant open: $!\n";
    while(read(BINFILE, $data, 3)){

    $data=hex(unpack 'H*',$data);
    if ($data & 0x800000) {$data |= 0xff000000};
    printf "%d \n", $data;

    }
    close (BINFILE) || die "Cant close: $!\n";

    Unless there is yet a more efficient method . . . .
    stylechief, Apr 12, 2005
    #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. Replies:
    10
    Views:
    6,192
    Neredbojias
    Aug 19, 2005
  2. Mantorok Redgormor

    sign magnitude, ones complement, two's complement

    Mantorok Redgormor, Oct 5, 2003, in forum: C Programming
    Replies:
    8
    Views:
    8,598
    Glen Herrmannsfeldt
    Oct 8, 2003
  3. sarathy

    1's complement and 2's complement

    sarathy, Aug 1, 2006, in forum: C Programming
    Replies:
    20
    Views:
    2,190
    Bo Persson
    Aug 2, 2006
  4. sarathy
    Replies:
    22
    Views:
    2,347
    Bo Persson
    Aug 2, 2006
  5. Roberto Waltman

    2's complement vs. 1's complement vs. ...

    Roberto Waltman, Jun 9, 2011, in forum: C Programming
    Replies:
    4
    Views:
    1,355
    Michael Press
    Jun 14, 2011
Loading...

Share This Page