Converting Bytes to a Negative Integer

Discussion in 'Ruby' started by Harris Reynolds, Feb 14, 2007.

  1. Let's say I have 4 bytes:=0A=0A255 255 255 236=0A=0AThe binary representati=
    on of this is:=0A=0A11111111 =0A11111111 =0A11111111 =0A11101100=0A=0AThe=
    decimal number should be -20. Does anyone know how to convert these 4 byt=
    es into an Integer?=0A=0A~harris=0A=0A=0A =0A______________________________=
    ______________________________________________________=0AAny questions? Get=
    answers on any topic at www.Answers.yahoo.com. Try it now.
     
    Harris Reynolds, Feb 14, 2007
    #1
    1. Advertising

  2. On Feb 14, 2007, at 2:27 PM, Harris Reynolds wrote:

    > Let's say I have 4 bytes:
    >
    > 255 255 255 236


    >> bytes = [255, 255, 255, 236].map { |b| b.chr }.join

    => "\377\377\377\354"

    > The binary representation of this is:
    >
    > 11111111
    > 11111111
    > 11111111
    > 11101100


    >> bytes.unpack("B*").first.scan(/[01]{8}/)

    => ["11111111", "11111111", "11111111", "11101100"]

    > The decimal number should be -20. Does anyone know how to convert
    > these 4 bytes into an Integer?


    This is where I had trouble. I found the following:

    >> bytes.reverse.unpack("l*").first

    => -20

    This is tied to my processor though. I had to reverse the bytes
    because they are not in the order my machine expects.

    unpack() has directives for when the order is known, but all of those
    seemed to be unsigned.

    I'm anxious to see the cross-platform solution for this...

    James Edward Gray II
     
    James Edward Gray II, Feb 14, 2007
    #2
    1. Advertising

  3. Harris Reynolds

    Tim Pease Guest

    Re: Converting Bytes to a Negative Integer

    On 2/14/07, James Edward Gray II <> wrote:
    > On Feb 14, 2007, at 2:27 PM, Harris Reynolds wrote:
    >
    > > Let's say I have 4 bytes:
    > >
    > > 255 255 255 236

    >
    > >> bytes = [255, 255, 255, 236].map { |b| b.chr }.join

    > => "\377\377\377\354"
    >
    > > The binary representation of this is:
    > >
    > > 11111111
    > > 11111111
    > > 11111111
    > > 11101100

    >
    > >> bytes.unpack("B*").first.scan(/[01]{8}/)

    > => ["11111111", "11111111", "11111111", "11101100"]
    >
    > > The decimal number should be -20. Does anyone know how to convert
    > > these 4 bytes into an Integer?

    >
    > This is where I had trouble. I found the following:
    >
    > >> bytes.reverse.unpack("l*").first

    > => -20
    >
    > This is tied to my processor though. I had to reverse the bytes
    > because they are not in the order my machine expects.
    >
    > unpack() has directives for when the order is known, but all of those
    > seemed to be unsigned.
    >
    > I'm anxious to see the cross-platform solution for this...
    >


    LITTLE_ENDIAN = [42].pack('i')[0] == 42

    bytes = [255, 255, 255, 236]
    str = bytes.pack('C*')
    str.reverse! if LITTLE_ENDIAN
    str.unpack('i')[0]



    Blessings,
    TwP
     
    Tim Pease, Feb 14, 2007
    #3
  4. Re: Converting Bytes to a Negative Integer

    On 2/14/07, James Edward Gray II <> wrote:
    > On Feb 14, 2007, at 2:27 PM, Harris Reynolds wrote:
    > > Let's say I have 4 bytes:
    > >
    > > 255 255 255 236

    >
    > >> bytes = [255, 255, 255, 236].map { |b| b.chr }.join

    > => "\377\377\377\354"
    >
    > > The binary representation of this is:
    > >
    > > 11111111
    > > 11111111
    > > 11111111
    > > 11101100

    >
    > >> bytes.unpack("B*").first.scan(/[01]{8}/)

    > => ["11111111", "11111111", "11111111", "11101100"]
    >
    > > The decimal number should be -20. Does anyone know how to convert
    > > these 4 bytes into an Integer?

    >
    > This is where I had trouble. I found the following:
    >
    > >> bytes.reverse.unpack("l*").first

    > => -20
    >
    > This is tied to my processor though. I had to reverse the bytes
    > because they are not in the order my machine expects.
    >
    > unpack() has directives for when the order is known, but all of those
    > seemed to be unsigned.
    >
    > I'm anxious to see the cross-platform solution for this...


    Joel VanDerWerf had something that I'll be adapting if I need it elsewhere.

    x = -123
    s = [x].pack("N")

    bits = 32
    max_unsigned = 2 ** bits
    max_signed = 2 ** (bits - 1)
    to_signed = proc { |n| (n >= max_signed) ? n - max_unsigned : n }

    puts to_signed[s.unpack("N").first]

    I need it for unsigned->signed words, so:

    x = -123
    s = [x].pack("n")

    bits = 16
    max_unsigned = 2 ** bits
    max_signed = 2 ** (bits - 1)
    to_signed = proc { |n| (n >= max_signed) ? n - max_unsigned : n }

    puts to_signed[s.unpack("n").first]

    -austin
    --
    Austin Ziegler * * http://www.halostatue.ca/
    * * http://www.halostatue.ca/feed/
    *
     
    Austin Ziegler, Feb 14, 2007
    #4
  5. On Feb 14, 2007, at 3:27 PM, Harris Reynolds wrote:

    > Let's say I have 4 bytes:
    >
    > 255 255 255 236
    >
    > The binary representation of this is:
    >
    > 11111111
    > 11111111
    > 11111111
    > 11101100
    >
    > The decimal number should be -20. Does anyone know how to convert
    > these 4 bytes into an Integer?


    Maybe this will help:

    data = ""
    [255, 255, 255, 236].each { |e| data << e }
    data # => "\377\377\377\354"
    data.unpack('l').first # => -20

    Regards, Morton
     
    Morton Goldberg, Feb 14, 2007
    #5
  6. On Feb 14, 2007, at 5:02 PM, Morton Goldberg wrote:

    > data = ""
    > [255, 255, 255, 236].each { |e| data << e }
    > data # => "\377\377\377\354"
    > data.unpack('l').first # => -20


    Watch what happens when I run the same code:

    >> data = ""

    => ""
    >> [255, 255, 255, 236].each { |e| data << e }

    => [255, 255, 255, 236]
    >> data

    => "\377\377\377\354"
    >> data.unpack('l').first

    => -318767105

    See my earlier post in this thread about this.

    James Edward Gray II
     
    James Edward Gray II, Feb 14, 2007
    #6
  7. On Feb 14, 2007, at 6:37 PM, James Edward Gray II wrote:

    > On Feb 14, 2007, at 5:02 PM, Morton Goldberg wrote:
    >
    >> data = ""
    >> [255, 255, 255, 236].each { |e| data << e }
    >> data # => "\377\377\377\354"
    >> data.unpack('l').first # => -20

    >
    > Watch what happens when I run the same code:
    >
    > >> data = ""

    > => ""
    > >> [255, 255, 255, 236].each { |e| data << e }

    > => [255, 255, 255, 236]
    > >> data

    > => "\377\377\377\354"
    > >> data.unpack('l').first

    > => -318767105


    I see your point. Many new computers have 64-bit CPUs and we should
    remember that. Also, you want to be sure I, lowly 32-bit CPU owner,
    envy you for having one of these <just kidding>.

    Regards, Morton
     
    Morton Goldberg, Feb 15, 2007
    #7
  8. On Feb 15, 2007, at 9:47 AM, Morton Goldberg wrote:

    > On Feb 14, 2007, at 6:37 PM, James Edward Gray II wrote:
    >
    >> On Feb 14, 2007, at 5:02 PM, Morton Goldberg wrote:
    >>
    >>> data = ""
    >>> [255, 255, 255, 236].each { |e| data << e }
    >>> data # => "\377\377\377\354"
    >>> data.unpack('l').first # => -20

    >>
    >> Watch what happens when I run the same code:
    >>
    >> >> data = ""

    >> => ""
    >> >> [255, 255, 255, 236].each { |e| data << e }

    >> => [255, 255, 255, 236]
    >> >> data

    >> => "\377\377\377\354"
    >> >> data.unpack('l').first

    >> => -318767105

    >
    > I see your point. Many new computers have 64-bit CPUs and we should
    > remember that. Also, you want to be sure I, lowly 32-bit CPU owner,
    > envy you for having one of these <just kidding>.


    I'll prop you back up then, this isn't a 32 to 64 bit (size) issue.
    It's an endian (order) issue:

    http://en.wikipedia.org/wiki/Endianness

    James Edward Gray II
     
    James Edward Gray II, Feb 15, 2007
    #8
  9. On Feb 15, 2007, at 11:04 AM, James Edward Gray II wrote:

    > On Feb 15, 2007, at 9:47 AM, Morton Goldberg wrote:
    >
    >> On Feb 14, 2007, at 6:37 PM, James Edward Gray II wrote:
    >>
    >>> On Feb 14, 2007, at 5:02 PM, Morton Goldberg wrote:
    >>>
    >>>> data = ""
    >>>> [255, 255, 255, 236].each { |e| data << e }
    >>>> data # => "\377\377\377\354"
    >>>> data.unpack('l').first # => -20
    >>>
    >>> Watch what happens when I run the same code:
    >>>
    >>> >> data = ""
    >>> => ""
    >>> >> [255, 255, 255, 236].each { |e| data << e }
    >>> => [255, 255, 255, 236]
    >>> >> data
    >>> => "\377\377\377\354"
    >>> >> data.unpack('l').first
    >>> => -318767105

    >>
    >> I see your point. Many new computers have 64-bit CPUs and we
    >> should remember that. Also, you want to be sure I, lowly 32-bit
    >> CPU owner, envy you for having one of these <just kidding>.

    >
    > I'll prop you back up then, this isn't a 32 to 64 bit (size)
    > issue. It's an endian (order) issue:


    Mea culpa -- I didn't see your point at all. Let's see if I've got it
    now.

    1. Your result couldn't the result of conversion into a 64-bit
    integer with big-endian byte order, because if that were the case we
    would see either -20 or a large positive number (if sign extension
    didn't occur).

    2. On my computer (iMac G5), I get

    [-20].pack('i') # => "\377\377\377\354"
    [-318767105].pack('i') # => "\354\377\377\377"

    and

    [-20].pack('N') # => "\377\377\377\354"
    [-318767105].pack('N') # => "\354\377\377\377"

    which shows it's big-endian because both unpack directives produce
    the same result.

    3. On your computer (which I think is also a Macintosh), you would get

    [-20].pack('i') # => "\354\377\377\377"
    [-318767105].pack('i') # => "\377\377\377\354"

    and

    [-20].pack('N') # => "\377\377\377\354"
    [-318767105].pack('N') # => "\354\377\377\377"

    which would show it's little-endian and, presumably, some kind of
    Intel-based Mac.

    Do I have it right now?

    Regards, Morton

    P.S. But I don't see how this props me back up :)
     
    Morton Goldberg, Feb 15, 2007
    #9
  10. On Feb 15, 2007, at 4:58 PM, Morton Goldberg wrote:

    > 2. On my computer (iMac G5), I get
    >
    > [-20].pack('i') # => "\377\377\377\354"
    > [-318767105].pack('i') # => "\354\377\377\377"
    >
    > and
    >
    > [-20].pack('N') # => "\377\377\377\354"
    > [-318767105].pack('N') # => "\354\377\377\377"
    >
    > which shows it's big-endian because both unpack directives produce
    > the same result.
    >
    > 3. On your computer (which I think is also a Macintosh), you would get


    Yes, it's an Intel Core Duo Mac.

    > [-20].pack('i') # => "\354\377\377\377"
    > [-318767105].pack('i') # => "\377\377\377\354"
    >
    > and
    >
    > [-20].pack('N') # => "\377\377\377\354"
    > [-318767105].pack('N') # => "\354\377\377\377"
    >
    > which would show it's little-endian and, presumably, some kind of
    > Intel-based Mac.


    Exactly.

    > Do I have it right now?


    Sure do.

    > P.S. But I don't see how this props me back up :)


    I wasn't lording 64 bit processing over you. ;)

    James Edward Gray II
     
    James Edward Gray II, Feb 16, 2007
    #10
    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. prem_eda
    Replies:
    5
    Views:
    7,991
    Pieter Hulshoff
    Oct 11, 2004
  2. Jason Collins
    Replies:
    3
    Views:
    6,073
    Jason Collins
    Feb 18, 2004
  3. mrby

    4-bytes or 8-bytes alignment?

    mrby, Nov 2, 2004, in forum: C Programming
    Replies:
    8
    Views:
    442
    Mark McIntyre
    Nov 2, 2004
  4. Replies:
    5
    Views:
    568
    Flash Gordon
    Apr 9, 2006
  5. Replies:
    15
    Views:
    12,095
    Eric Sosman
    Jun 23, 2006
Loading...

Share This Page