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