```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:
>
>
>    negative = "" << 0xF2 << 0x34 << 0x56 << 0x78
>    assert_equal -231451016, signed4(StringIO.new(negative))
>  end
>
>    positive = "" << 0x02 << 0x34 << 0x56 << 0x78
>    assert_equal 36984440, signed4(StringIO.new(positive))
>  end
>
> end
>
> The Solution:
>
> def signed4(file)
>  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"
MAX_POS = 2 ** 31 -1
BIG_ENDIAN = [42].pack('N') == [42].pack('i')
positive = [0x02, 0x34, 0x56, 0x78].pack "c*"
assert_equal 36984440, signed4(positive)
end
negative = [0xF2, 0x34, 0x56, 0x78].pack "c*"
assert_equal -231451016, signed4(negative)
end
def signed4 buf
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
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
===============================================================================

```