Ryan D Haase
Ryan D Haase

Reputation: 79

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.

Upvotes: 3

Views: 6203

Answers (2)

lurker
lurker

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

aarti
aarti

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.

  1. First we write out 28 in binary form. 00011100

  2. Then we invert the digits. 0 becomes 1, 1 becomes 0. 11100011

  3. Then we add 1. 11100100

Upvotes: 1

Related Questions