# Converting Bytes to a Negative Integer

**URL:** <https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364>\
**Category:** ruby-talk\
**Created:** [14 February 2007 20:27 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364 "2007-02-14T20:27:56Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Harris\_Reynolds](https://avatars.discourse-cdn.com/v4/letter/h/3e96dc/32.png) [@Harris\_Reynolds](https://rubytalk.org/u/Harris_Reynolds)\
**Post date:** [14 February 2007 20:27 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/1 "2007-02-14T20:27:56Z")

</div>

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?

~harris

> **···**
>
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_  
> Any questions? Get answers on any topic at [www.Answers.yahoo.com](http://www.Answers.yahoo.com). Try it now.

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [14 February 2007 21:53 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/2 "2007-02-14T21:53:44Z")

</div>

> 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  
> 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

> **···**
>
> On Feb 14, 2007, at 2:27 PM, Harris Reynolds wrote:

---

<div class="post-metadata">

**Author:** ![Morton\_Goldberg](https://avatars.discourse-cdn.com/v4/letter/m/7ea924/32.png) [@Morton\_Goldberg](https://rubytalk.org/u/Morton_Goldberg)\
**Post date:** [14 February 2007 23:02 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/3 "2007-02-14T23:02:07Z")

</div>

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

> **···**
>
> 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  
> > 11101100
> > 
> > The decimal number should be -20. Does anyone know how to convert these 4 bytes into an Integer?

---

<div class="post-metadata">

**Author:** ![Tim\_Pease](https://avatars.discourse-cdn.com/v4/letter/t/3e96dc/32.png) [@Tim\_Pease](https://rubytalk.org/u/Tim_Pease)\
**Post date:** [14 February 2007 22:11 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/4 "2007-02-14T22:11:04Z")

</div>

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

> **···**
>
> On 2/14/07, James Edward Gray II \<james@grayproductions.net\> 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  
> > \> 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...

---

<div class="post-metadata">

**Author:** ![Austin\_Ziegler5](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/austin_ziegler5/32/1985_2.png) [@Austin\_Ziegler5](https://rubytalk.org/u/Austin_Ziegler5)\
**Post date:** [14 February 2007 22:13 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/5 "2007-02-14T22:13:40Z")

</div>

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

&nbsp;&nbsp;x = -123  
&nbsp;&nbsp;s = .pack("N")

&nbsp;&nbsp;bits = 32  
&nbsp;&nbsp;max\_unsigned = 2 \*\* bits  
&nbsp;&nbsp;max\_signed = 2 \*\* (bits - 1)  
&nbsp;&nbsp;to\_signed = proc { |n| (n \>= max\_signed) ? n - max\_unsigned : n }

&nbsp;&nbsp;puts to\_signed[s.unpack("N").first]

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

&nbsp;&nbsp;x = -123  
&nbsp;&nbsp;s = .pack("n")

&nbsp;&nbsp;bits = 16  
&nbsp;&nbsp;max\_unsigned = 2 \*\* bits  
&nbsp;&nbsp;max\_signed = 2 \*\* (bits - 1)  
&nbsp;&nbsp;to\_signed = proc { |n| (n \>= max\_signed) ? n - max\_unsigned : n }

&nbsp;&nbsp;puts to\_signed[s.unpack("n").first]

-austin

> **···**
>
> On 2/14/07, James Edward Gray II \<james@grayproductions.net\> 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  
> > \> 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...
> 
> --  
> Austin Ziegler \* halostatue@gmail.com \* [http://www.halostatue.ca/](http://www.halostatue.ca/)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* austin@halostatue.ca \* [You are in a maze of twisty little passages, all alike. // halo • statue](http://www.halostatue.ca/feed/)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* austin@zieglers.ca

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [14 February 2007 23:37 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/6 "2007-02-14T23:37:45Z")

</div>

> 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

> **···**
>
> On Feb 14, 2007, at 5:02 PM, Morton Goldberg wrote:

---

<div class="post-metadata">

**Author:** ![Morton\_Goldberg](https://avatars.discourse-cdn.com/v4/letter/m/7ea924/32.png) [@Morton\_Goldberg](https://rubytalk.org/u/Morton_Goldberg)\
**Post date:** [15 February 2007 15:47 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/7 "2007-02-15T15:47:03Z")

</div>

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

> **···**
>
> 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

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [15 February 2007 16:04 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/8 "2007-02-15T16:04:20Z")

</div>

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

> **[Endianness](https://en.wikipedia.org/wiki/Endianness)**
>
> In computing, endianness is the order or sequence of bytes of a word of digital data in computer memory or data communication which is identified by describing the impact of the "first" bytes, meaning at the smallest address or sent first. Endianness is primarily expressed as big-endian (BE) or little-endian (LE), terms introduced by Danny Cohen into computer science for data ordering in an Internet Experiment Note published in 1980. The adjective endian has its origin in the writings of 18th Co...

James Edward Gray II

> **···**
>
> 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\>.

---

<div class="post-metadata">

**Author:** ![Morton\_Goldberg](https://avatars.discourse-cdn.com/v4/letter/m/7ea924/32.png) [@Morton\_Goldberg](https://rubytalk.org/u/Morton_Goldberg)\
**Post date:** [15 February 2007 22:58 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/9 "2007-02-15T22:58:15Z")

</div>

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 🙂

> **···**
>
> 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:

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [16 February 2007 03:21 UTC](https://rubytalk.org/t/converting-bytes-to-a-negative-integer/35364/10 "2007-02-16T03:21:56Z")

</div>

> 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

> **···**
>
> On Feb 15, 2007, at 4:58 PM, Morton Goldberg wrote:
