1

true如果num是 2 的幂,我有此代码要返回。

def is_power_of_two?(num)
  result = num.inject(0) {|n1, n2| n2 ** n1}
  if result == num
    true
  else
    false
  end
end

p is_power_of_two?(16)

我一直收到错误消息。我怎样才能修复和简化这段代码?

4

8 回答 8

8

显然,n是一个非负整数。

代码

def po2?(n)
  n.to_s(2).count('1') == 1
end

例子

po2?  0     #=> false
po2?  1     #=> true
po2? 32     #=> true
po2? 33     #=> false

解释

Fixnum#to_s为给定的基数提供整数(接收器)的字符串表示形式。该方法的参数(默认为 10)是基数。例如:

16.to_s     #=> "16" 
16.to_s(8)  #=> "20" 
16.to_s(16) #=> "10"
15.to_s(16) #=>  "f"

我们感兴趣的是以 2 为底。对于 2 的幂:

 1.to_s(2)  #=>      "1" 
 2.to_s(2)  #=>     "10" 
 4.to_s(2)  #=>    "100" 
 8.to_s(2)  #=>   "1000"
16.to_s(2)  #=>  "10000"

对于一些不是 2 的幂的自然数:

 3.to_s(2)  #=>    "11" 
 5.to_s(2)  #=>   "101" 
11.to_s(2)  #=>  "1011" 

因此,我们希望匹配包含一个的二进制字符串1

另一种方式

R = /
    \A      # match beginning of string ("anchor")
    10*     # match 1 followed by zero or more zeroes
    \z      # match end of string ("anchor")
    /x      # free-spacing regex definition mode

def po2?(n)
  (n.to_s(2) =~ R) ? true : false
end

po2?(4)  #=> true
po2?(5)  #=> false

还有一个用于道路

这使用Fixnum#bit_lengthFixnum#[]

def po2?(n)
  m = n.bit_length-1
  n[m] == 1 and m.times.all? { |i| n[i].zero? }
end

po2?  0     #=> false
po2?  1     #=> true
po2? 32     #=> true
po2? 33     #=> false
于 2015-07-22T22:41:18.137 回答
5

尝试:

def is_power_of_two?(num)
  num != 0 && (num & (num - 1)) == 0
end

这里解释得很好(对于 C#,但@GregHewgill 的解释也适用于这里)

于 2015-07-22T21:49:15.110 回答
2

我会做这样的事情,使用 Ruby 的Math模块。

def power_of_two?(n)
  Math.log2(n) % 1 == 0
end

或者,如果你想变得很酷:

def power_of_two?(n)
  (Math.log2(n) % 1).zero?
end

一些 IRB 输出:

2.1.0 :004 > power_of_two?(2)
 => true
2.1.0 :005 > power_of_two?(32768)
 => true
2.1.0 :006 > power_of_two?(65536)
 => true

此方法假定输入为正整数。

资源

于 2015-07-22T22:05:28.453 回答
1

解决这个问题的另一种方法是与这里的大多数答案相反——我们可以使用数字 1 开始并找出数字是否是 2 的幂。像这样:

def power_of_two?(num)
  product = 1

  while product < num
    product *= 2
  end
  product == num
end

我们从 1 开始。然后我们将 1 乘以 2,并继续乘以 2,直到乘积大于num( product < num)。一旦我们达到那个条件,我们就会停止,退出循环,并检查它是否等于num( product == num)。如果是,则num是 2 的幂。

于 2019-04-19T18:43:08.643 回答
0

正如上面评论中所指出的,您遇到错误是因为您尝试inject在不可迭代(int)上使用该方法。这是使用建议的解决方案log2

def is_power_of_two?(num)
  result = Math.log2(num)
  result == Integer(result)
end

注意:将因接近二进制的非常大的数字而失败(如 2 ^ 64 - 1)。一个万无一失的版本(但速度较慢)是:

def is_power_of_two?(num)
  while (num % 2 == 0 and num != 0)
    num /= 2
  end
  num == 1
end

请评论你们中的任何人可能发现的任何改进。

于 2015-07-22T21:43:36.063 回答
0

这是另一个使用递归的解决方案:

def power_of_2?(number)
 return true if number == 1
 return false if number == 0 || number % 2 != 0
 power_of_2?(number / 2)
end
于 2015-07-23T17:26:47.903 回答
0

在我看来,最简单——但可能有点长——做你需要做的事情的方法就是像这样编写这个递归方法:

def power_of_two?(number)
    continue = true
    if number == 1
        return true
    end
    if number % 2 != 0
        return false
    else
        while continue == true do
            if number.to_f / 2.0 == 2.0
                continue = false
                return true
            else
                if number % 2 != 0
                    continue = false 
                    return false
                else
                    number /= 2
                    continue = true
                end
            end
        end
    end
end

1 是 2 的幂 (2^0),因此它首先检查给定的数字是否为 1。如果不是,则检查它是否为奇数,因为 1 是唯一一个为 2 的幂的奇数。

如果它是奇数,则返回 false 并继续执行 else 语句。它将检查数字除以 2 是否为 2,因为这样显然是 2 的幂。它以浮点数的形式执行此操作,因为 Ruby 中的 5/2 将返回 2。

如果这是错误的,它会再次检查数字是否为奇数——第一轮不需要,之后需要。如果数字不是奇数,它会将数字除以二,然后再循环一次。

这将一直持续到程序通过获取 2 或任何奇数自行解决,并分别返回 true 或 false。

于 2015-07-24T01:01:55.110 回答
0

我在训练营应用程序准备中遇到了这个。我不是数学人,也不懂其中一些方法,所以我想为像我这样的人提交一个常识方法。这需要很少的数学知识,除了知道一个数字的二次方将是某个数字自身相乘的结果。

def is_power_of_two?(num)
  num.times  {|n| return true if (n+1) * (n+1) == num}
  false
end

此方法从 1 开始计数到 ​​num 变量,如果(序列中的任何这些数字乘以自身)等于 num 并且如果 num 不为 0(下面将详细介绍),则返回 true。

示例:数字 = 9

1 * 1 == 9 #=> false
2 * 2 == 9 #=> false
3 * 3 == 9 #=> true 

返回 true 并且方法完成运行。

#times 方法需要一个大于 0 的整数,因此这种边缘情况是“处理”的,因为 #times 不使用“0”作为变量,并且在 #times 迭代之外返回 false。

于 2017-09-11T17:32:12.767 回答