Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Integers to Binary in Ruby

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.

like image 424
Ryan D Haase Avatar asked Nov 27 '25 20:11

Ryan D Haase


1 Answers

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
like image 109
lurker Avatar answered Nov 29 '25 16:11

lurker



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!