Ruby中整数到二进制的转换

Ruby中整数到二进制的转换,ruby,binary,integer,Ruby,Binary,Integer,我正在编写一个codewars kata,并且遇到了两个失败的测试用例 kata描述如下: 把整数转换成二进制就这么简单。您将得到一个整数作为参数,并且必须返回其二进制形式。要了解如何将十进制数转换为二进制数,请访问此处 注:负数应作为2的补码处理;假设所有数字都是使用任何语言中的4字节(或32位)存储的整数 我的代码: def to_binary(n) temp_array = [] if n == 0 temp_array << 0 elsif n <

我正在编写一个codewars kata,并且遇到了两个失败的测试用例

kata描述如下: 把整数转换成二进制就这么简单。您将得到一个整数作为参数,并且必须返回其二进制形式。要了解如何将十进制数转换为二进制数,请访问此处

注:负数应作为2的补码处理;假设所有数字都是使用任何语言中的4字节(或32位)存储的整数

我的代码:

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

我怀疑失败的测试带有负整数,因为第一个失败测试的预期输出是
1111111111111 0000011000
,这意味着正参数值是
4294966296
,或者它是负的。如果我运行
to_binary(4294966296)
我会得到预期的输出。

我不喜欢这种方法,因为我确信有一种更聪明和/或更紧凑的Ruby风格的方法来实现它。但是,使用将二进制数字加载到数组中,然后合并的方法,您可以以更直接的方式完成:

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
然而,处理消极与非消极的不对称性有点令人讨厌。你可以这样做:

def to_binary(n)
  31.downto(0).map { |b| n[b] }.join.sub(/^0*/, "")
end

这不是生成2的补码的传统算法,所以我不确定它是否有助于您理解二进制转换,但您可以在ruby中这样做以帮助检查您的答案

注:此项仅适用于负数

32.downto(0).map { |n| -4294966296[n] }.join
=> "100000000000000000000001111101000"
对于2的补码计算,最好使用较低级别的语言(如C)实现,以了解算法。聪明的方法掩盖了步骤,只是给你一个答案

假设我们使用的是8位(为了简单起见),假设我们想找到-28如何用2的补码表示法表示

  • 首先我们用二进制形式写出28。 00011100

  • 然后我们反转数字。0变为1,1变为0。 11100011

  • 然后我们加1。 11100100


  • 我假设你想写这个算法,即使ruby有一个内置的转换'10.to_s(2)=>“1010”@500_错误,除了
    (-10)。to_s(2)=>“-1010”
    @潜伏者考虑到负二进制值实际上并不存在,这是一个合理的解释。表示这些的常用符号是,但这并不是唯一的方法。@tadman当然,但我要说的是,它并不能解决OP查找32位2的补码结果的问题。啊,刚才看到了这一部分。在
    到_s(2)
    之前,通过一些操作将值偏移,没有什么是无法修复的。有一种聪明的方法32.向下到(0).映射{n |-4294966296[n]}.join=>“1000000000000000000001111000”@500_错误是的,这很好。唯一剩下的问题是,例如,
    32.downto(0).map{n | 2[n]}.join=>00000000000000000000000010
    但是OP需要“10”。是的,它很聪明,但不确定它是否是OP用例的好答案。应该有一些位移位以便理解转换。谢谢@Louger和@500_错误,这只做了一个小改动:
    ruby def to_binary(n)if n>=0 n to_s(2)else 31.downto(0).map{b | n[b]}。join end end
    原始方法允许该方法最多返回33位,而不是32位。这个方法也比我用的短得多。我对ruby还是个新手,将剖析这个方法以更好地理解它谢谢大家!+谢谢你那漂亮的表情<代码>32.downto(0).map{n | 2[n]}.join=>“00000000000000000000000000000010”产生
    “00000000000000000010”
    而不是
    “10”
    。也许这个好方法有一个小的修改来修复它。@lower你可以转换成一个整数来压扁前导的零…
    x=2;32.downto(0).map{124; n | x[n]}.join.to_i
    如果坚持结果是字符串,只需将其转换回
    x=2;32.downto(0).map{n|x[n]}.join.to_i.to_s
    @SteveTurczyn yep,绝对正确。我假设OP需要字符串输出(因为他们希望输出为“二进制”表示)。
    def to_binary(n)
      31.downto(0).map { |b| n[b] }.join.sub(/^0*/, "")
    end
    
    32.downto(0).map { |n| -4294966296[n] }.join
    => "100000000000000000000001111101000"