From: "Ara.T.Howard" Date: 2005-11-16T02:56:09+09:00 Subject: Re: Solution Comments on Re: Reading a signed byte in network byte order On Wed, 16 Nov 2005, Robert Evans wrote: > Hi, > > So, I came up with a solution, and would be grateful for Ruby style tips. It > seemed a lot harder to do than it needed to be. > > Any help appreciated. > > Thanks, > Bob > > The Tests: > > class ByteReaderTest < Test::Unit::TestCase > > def test_read_signed4_negative > negative = "" << 0xF2 << 0x34 << 0x56 << 0x78 > assert_equal -231451016, signed4(StringIO.new(negative)) > end > > def test_read_signed4_positive > positive = "" << 0x02 << 0x34 << 0x56 << 0x78 > assert_equal 36984440, signed4(StringIO.new(positive)) > end > > end > > The Solution: > > def signed4(file) > bits = (file.read(4).unpack('B32'))[0] > if bits[0..0].eql? "0" # sign bit is positive > bits.to_i(2) > else # sign bit is negative > compute_negative_number_from(bits) > end > end > > def compute_negative_number_from(bits) > twos_complement = flip(bits).join.to_i(2) + 1 > -1 * twos_complement > end > > def flip(bits) > bits.scan(/\w/).collect { |bit| (bit.eql?("1")) ? "0" : "1" } > end harp:~ > cat a.rb require "test/unit" class ByteReaderTest < Test::Unit::TestCase MAX_POS = 2 ** 31 -1 BIG_ENDIAN = [42].pack('N') == [42].pack('i') def test_read_signed4_positive positive = [0x02, 0x34, 0x56, 0x78].pack "c*" assert_equal 36984440, signed4(positive) end def test_read_signed4_negative negative = [0xF2, 0x34, 0x56, 0x78].pack "c*" assert_equal -231451016, signed4(negative) end def signed4 buf buf = buf.read 4 if buf.respond_to? "read" raise RangeError unless buf.size == 4 n = buf.unpack('N').first if n > MAX_POS (BIG_ENDIAN ? buf : buf.reverse).unpack('l').first else n end end end harp:~ > ruby a.rb Loaded suite a Started .. Finished in 0.000583 seconds. 2 tests, 2 assertions, 0 failures, 0 errors -a -- =============================================================================== | ara [dot] t [dot] howard [at] gmail [dot] com | all happiness comes from the desire for others to be happy. all misery | comes from the desire for oneself to be happy. | -- bodhicaryavatara ===============================================================================