From: Harris Reynolds Date: 2007-02-16T00:32:18+09:00 Subject: Re: Converting Bytes to a Negative Integer I really like the to_signed proc idea at the bottom of this message... the procedure doesn't work however in all cases... note the Ruby code below: bits = 32 max_unsigned = 2 ** bits max_signed = 2 ** (bits - 1) to_signed = proc { |n| (n >= max_signed) ? n - max_unsigned : n } x = -123 s = [x].pack("N") puts to_signed[s.unpack("N").first] y = 7777777 s = [y].pack("N") puts to_signed[s.unpack("N").first] # try converting 7777777 when you already have the bytes z = "" [129, 237, 173, 241].each { |e| z << e } puts to_signed[z.unpack("N").first] # OUTPUT >ruby signed_test.rb -123 7777777 -2115129871 Coverting the bytes of 7777777 yields a pretty nasty negative number in this case. ~harris 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 * halostatue@gmail.com * http://www.halostatue.ca/ * austin@halostatue.ca * http://www.halostatue.ca/feed/ * austin@zieglers.ca ____________________________________________________________________________________ Cheap talk? Check out Yahoo! Messenger's low PC-to-Phone call rates. http://voice.yahoo.com ____________________________________________________________________________________ Food fight? Enjoy some healthy debate in the Yahoo! Answers Food & Drink Q&A. http://answers.yahoo.com/dir/?link=list&sid=396545367