有没有办法强制ruby以二进制形式输出结果

时间:2016-06-22 00:49:14

标签: ruby binary

我想为一些同行做一个演示,我想强制IRB只返回二进制值。

例如,无论输入在哪个基数,它当前都会在基数10中返回结果:

0b1111
# => 15 #should return 1111 or 0b1111
0b0001 | 0b0011
# => 3 #should return 0011 or 0b0011

有没有办法强制这个结果?我想演示按位运算符,他们更容易理解,如果他们看到流出的位而不是返回的基数为10,那么之后我将不得不转换为基数2.

此外,我希望所有结果都是4位的倍数。如果可能,使用下划线或空格分隔半字节分组。

例如:

0b0001_0101
# => 0b0001_0101 #or 0b0001 0101, or 0001 0101, or 0001_0101

如果我的结果不需要用4位(例3,11)表示,则根据数字将其填充为4,8,16位。

1 个答案:

答案 0 :(得分:1)

如果你写0b0001.class,你会发现它是Fixnum。

撰写puts 0b1000会显示8,并且很清楚此Fixnum存储在基础10中。

因此,据我所知,没有任何方法可以阻止转换为10。

如果要控制Fixnum对象在IRB中的显示方式,可以为该类实现自定义inspect方法:

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

结果:

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

inspect方法使用to_s(2),它接受​​一个整数并生成一个二进制的字符串表示。但是,当二进制文件转换为基数10时,二进制文件前面的零点会丢失。这就是检查方法的原因。 需要手动将零添加到字符串的前面。

我无法想象以完全动态的方式在字符串的前面添加正确数量的零。

我在这里做的是计算可以包含未填充的二进制字符串的最小宽度(以4的倍数)。因此,如果未填充长度为5个字符,则最终宽度为8.如果未填充长度为2,则最终长度为4.

您可以选择将binary_width设置为在运行时更改的外部变量,然后从inspect函数引用它,而不是在运行中计算它。