How to Return a Fixed Length Binary Representation of an Integer in Ruby

How to return a fixed length binary representation of an integer in Ruby?

Use string format.

"%08b" % 1
# => "00000001"

Converting Integers to Binary in Ruby

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

Ruby Convert integer to binary to integer array of set bits

This would work:

i = 98
(0...i.bit_length).map { |n| i[n] << n }.reject(&:zero?)
#=> [2, 32, 64]
  • Fixnum#bit_length returns the position of the highest "1" bit
  • Fixnum#[n] returns the integer's nth bit, i.e. 0 or 1
  • Fixnum#<< shifts the bit to the left. 1 << n is equivalent to 2n

Step by step:

(0...i.bit_length).map { |n| i[n] }
#=> [0, 1, 0, 0, 0, 1, 1]

(0...i.bit_length).map { |n| i[n] << n }
#=> [0, 2, 0, 0, 0, 32, 64]

(0...i.bit_length).map { |n| i[n] << n }.reject(&:zero?)
#=> [2, 32, 64]

You might want to reverse the result.

In newer versions of Ruby (2.7+) you could also utilize filter_map and nonzero? to remove all 0 values:

(0...i.bit_length).filter_map { |n| (i[n] << n).nonzero? }
#=> [2, 32, 64]

Is there a way to force ruby to output results in binary

If you write 0b0001.class you will find that it is Fixnum.

Writing puts 0b1000 shows 8, and it's clear this Fixnum is stored in base 10.

So as far as I'm aware, there isn't any way to prevent the conversion to base 10.

If you want to control the way that Fixnum objects are displayed in IRB, you can implement a custom inspect method for the class:

class Fixnum
def inspect
unpadded_binary_string = to_s(2)
binary_width = if unpadded_binary_string.length % 4 == 0
unpadded_binary_string.length
else
((unpadded_binary_string.length / 4) * 4) + 4
end
padded_binary_string = "%0#{binary_width}d" % unpadded_binary_string
# join groups of 4 with an underscore
padded_binary_string = padded_binary_string.scan(/.{4}/).join("_")
"0b" + padded_binary_string
end
end

results:

irb(main):007:0> 0b1000
=> 0b1000
irb(main):011:0> 99999999
=> 0b0101_1111_0101_1110_0000_1111_1111

The inspect method uses to_s(2), which takes an integer and produces a string representation of it's binary. But the zeroes at the front of the binary are lost when it's converted to base 10. That's why the inspect method
needs to manually add zeroes to the front of the string.

There's no way I can think of to add the correct number of zeroes to the front of the string in a completely dynamic way.

What I'm doing here is calculating the minimum width (in a multiple of 4) that can contain the unpadded binary string. So if the unpadded length is 5 characters, the final width will be 8. If the unpadded length is 2, the final length is 4.

Instead of calculating it on-the-go, you could alternatively set the binary_width as an external variable that you change at runtime, then reference it from the inspect function.

Ruby binary string to hexadecimal without loosing 0000

You can use this:

binary = "0000010000000000000000000000000000000000000000000000000000000000"
[binary].pack("B*").unpack("H*").first
# => "0400000000000000"

binary.to_i(2) will convert the value to a number. A number does not know about leading zeros. pack("B*") will convert 8 bit each to a byte, giving you a binary encoded String. 8 x 0 is "\x00", a zero byte. So unlike the number, the string preserves the leading zeros. unpack("H*") then converts 4 bits each into their hex representation. See Array#pack and String#unpack for more information.

Decomposing an integer into an array of integers by bit manipulation

def decompose n, l, a = []
n, r = n.divmod(2 ** l)
a.unshift(r)
n.zero? ? a : decompose(n, l, a)
end

decompose(100, 4) # => [6, 4]
decompose(123456, 6) # => [30, 9, 0]

Looping through bits in an integer, ruby

To determine the length of the longest sequence of consecutive 1's, this is more efficient:

def longest_one_chain(n)
c = 0
while n != 0
n &= n >> 1
c += 1
end
c
end

The method simply counts how many times you can "bitwise AND" the number with itself shifted 1 bit to the right until it is zero.

Example:

                 ______ <-- longest chain
01011011100001111110011110101010 c=0
AND 0101101110000111111001111010101
1001100000111110001110000000 c=1, 1’s deleted
AND 100110000011111000111000000
100000011110000110000000 c=2, 11’s deleted
AND 10000001111000011000000
1110000010000000 c=3, 111’s deleted
AND 111000001000000
110000000000000 c=4, 1111’s deleted
AND 11000000000000
10000000000000 c=5, 11111’s deleted
AND 1000000000000
0 c=6, 111111’s deleted

What does the .size on number mean in ruby?

I always suggest to check the method you're not sure about using the following scheme:

  1. Check where the method comes from (using Object#method):

    number.method(:size)
    #=> #<Method: Fixnum#size>
  2. Open docs and learn what it does for Fixnum#size and how it works.

    2.1 If you're using IRB, you can run help 'Fixnum#size' to get the docs right in your console
    2.2 If you're using pry, you can go with show-doc Fixnum#size (install pry-doc gem first)


In Ruby 2.1.8 method was defined in Fixnum#size.

Starting from Ruby 2.4 it's defined in
Integer#size:

Returns the number of bytes in the machine representation of int.

Ruby to_s conversion to binary argument error

I think you are trying to convert a number in Ruby to a string with it's binary representation. This is possible with (if the number is actually a number in Ruby, e.g. Fixnum) :

4.to_s 2
# => "100"

But in your case, what you are getting after calling gets is a string, and the to_s method of the String class simply returns itself, and doesn't take any arguments, hence the error.

You can fix it by calling gets.to_i instead of just gets, so the read string of contents will be converted to an integer in Ruby (you should be sure that you will only be reading numbers at there).

And I believe you are trying to assign the binary representation (as a string) of n into the variable n2, for that you should be doing

n2 = n.to_s(2)

If you just do :

(n2=n).to_s

Because of the parenthesis, first n2 will be assigned the value of n, then to_s will be called on n2, the string version of n2 will be returned, and nothing else happens. First thing you should be doing is the conversion, then the assignment.

And also you should pass in a string while calling String#count, i.e. you should call n2.count('2') instead of n2.count(2).



Related Topics



Leave a reply



Submit