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)
我一直收到错误消息。我怎样才能修复和简化这段代码?
显然,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_length和Fixnum#[]:
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
尝试:
def is_power_of_two?(num)
num != 0 && (num & (num - 1)) == 0
end
这里解释得很好(对于 C#,但@GregHewgill 的解释也适用于这里)
我会做这样的事情,使用 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
此方法假定输入为正整数。
解决这个问题的另一种方法是与这里的大多数答案相反——我们可以使用数字 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 的幂。
正如上面评论中所指出的,您遇到错误是因为您尝试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
请评论你们中的任何人可能发现的任何改进。
这是另一个使用递归的解决方案:
def power_of_2?(number)
return true if number == 1
return false if number == 0 || number % 2 != 0
power_of_2?(number / 2)
end
在我看来,最简单——但可能有点长——做你需要做的事情的方法就是像这样编写这个递归方法:
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。
我在训练营应用程序准备中遇到了这个。我不是数学人,也不懂其中一些方法,所以我想为像我这样的人提交一个常识方法。这需要很少的数学知识,除了知道一个数字的二次方将是某个数字自身相乘的结果。
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。