Reputation: 79
I'm working on a codewars kata and stuck with 2 test cases that are failing.
The kata description is: Convert integers to binary as simple as that. You would be given an integer as a argument and you have to return its binary form. To get an idea about how to convert a decimal number into a binary number, visit here.
Notes: negative numbers should be handled as two's complement; assume all numbers are integers stored using 4 bytes (or 32 bits) in any language.
My code:
def to_binary(n)
temp_array = []
if n == 0
temp_array << 0
elsif n < 0
n = n % 256
while n > 0 do
temp_array << (n % 2)
n = (n / 2)
end
while temp_array.length < 32 do
temp_array << 1
end
else
while n > 0 do
temp_array << (n % 2)
n = (n / 2)
end
end
binary = temp_array.reverse.join
end
The test cases are:
Test Passed: Value == "10"
Test Passed: Value == "11"
Test Passed: Value == "100"
Test Passed: Value == "101"
Test Passed: Value == "111"
Test Passed: Value == "1010"
Test Passed: Value == "11111111111111111111111111111101"
Test Passed: Value == "0"
Test Passed: Value == "1111101000"
Test Passed: Value == "11111111111111111111111111110001"
Expected: "11111111111111111111110000011000", instead got: "11111111111111111111111111111000"
Expected: "11111111111100001011110111000001", instead got: "11111111111111111111111111000001"
Test Passed: Value == "11110100001000111111"
I suspect the tests that are failing are with negative integers because the first failing test's expected output is 11111111111111111111110000011000
which means that either the positive argument value was 4294966296
or it was negative. If I run to_binary(4294966296)
I get the expected output.
Upvotes: 3
Views: 6203
Reputation: 58244
I am not fond of this approach since I'm sure there's an even more clever and/or compact, Ruby-esque way of accomplishing it. But using your method of loading binary digits into an array, and then joining, what you have can be done in a little more straight-forward fashion:
def to_binary(n)
return "0" if n == 0
r = []
32.times do
if (n & (1 << 31)) != 0
r << 1
else
(r << 0) if r.size > 0
end
n <<= 1
end
r.join
end
Or, using @500_error's suggestion:
def to_binary(n)
if n >= 0
n.to_s(2)
else
31.downto(0).map { |b| n[b] }.join
end
end
The asymmetry to deal with negative versus non-negative is a little annoying, though. You could do something like:
def to_binary(n)
31.downto(0).map { |b| n[b] }.join.sub(/^0*/, "")
end
Upvotes: 8
Reputation: 2865
This is not a traditional algorithm to generate 2's complement, so I am not sure if it helps you in understanding binary conversion, but you can do this in ruby to help check your answers.
Note: This applies to negative number's only.
32.downto(0).map { |n| -4294966296[n] }.join
=> "100000000000000000000001111101000"
For 2's complement computation, it's best to implement using a lower level language like C, to get a sense of the algorithm. The clever approaches mask the steps and just give you an answer.
Suppose we're working with 8 bits (for simplicity's sake) and suppose we want to find how -28 would be expressed in two's complement notation.
First we write out 28 in binary form. 00011100
Then we invert the digits. 0 becomes 1, 1 becomes 0. 11100011
Then we add 1. 11100100
Upvotes: 1