今天偶然发现了这个编码挑战,目标是检查n是否是2的幂。虽然我的解决方案似乎通过了所有测试,但大家都不太满意。
首先,它似乎与之前编写的伪代码不匹配,当尝试将n与大于测试中使用的数字进行比较时,即:while n < 10:
我遇到了一个无限循环。
我很难理解这个问题!
我听说过有目的地引入一个不确定循环;这是不是某种抽象概念?
def is_power_of_two(n):
# Check if the number can be divided by two without a remainder
while n % 2 != n:
n = n / 2
# If after dividing by two the number is 1, it's a power of two
if n == 1:
return True
return False
print(is_power_of_two(0)) # Should be False
print(is_power_of_two(1)) # Should be True
print(is_power_of_two(8)) # Should be True
print(is_power_of_two(9)) # Should be False
3条答案
按热度按时间sbdsn5lh1#
这个算法实际上可以完全不用循环来求解。
如果选择使用位移位,则算法如下所示:
给定一个数字
n
,您可以使用1 << number of bits - 1
的位移位以及对n
的相等性检查。如果该数字是2的幂,则返回零(True
),否则返回非零值(False
)。示例:
数字8占用4位:
0b1000
。左移三位(1 << 3
)并进行等于8的检查(0b1000 == 8
)将返回True。但是,数字10也占用四位:然而,一位左移3(0b1000
),用8(0b1010 == 8
)的相等性检查返回假。测试:
5vf7fwbs2#
该代码似乎对许多输入都很有效,但它依赖于浮点数,通过应用(非整数)除以2。如果最后
n
为1,那么原始数字确实是2的幂。然而,由于浮点数的限制,这将打破足够大的输入,你会得到假阳性。
例如:
这个函数应该返回
False
,因为这个数字中有两个1位,但是你的函数会返回True
,就好像输入是1<<80
一样。要获得正确的实现,应该使用整数除法(
//
),并且只要余数为0就一直循环。回到无限循环的主题:它不能无限循环,因为
n
通过除法变得更小,并且最终,当n % 2 == n
时,它将变得低于值2。即使
n
为负......在这种情况下,它将通过除法保持为负,但同样由于浮点数限制,除法最终将给出0,此时循环条件满足。如果输入为0,则基于整数的版本可能会永远循环,并且需要保护。我们可以利用这个机会捕获负输入:
现在,上面的测试用例将返回正确的结果。
请注意,您可以使用一些按位操作符来完成此操作,而无需显式循环:
或者可能更可读:
rkue9o1l3#
这适用于较小的数字:
但是对于更大的数字,它的精度会受到Python浮点精度的影响,所以,你可以使用以下代码:
这是利用一个数字是2的幂的事实,如果在二进制中,它的前导数字之后没有其他的1(例如2 = 10,4 = 100,8 = 1000,等等)。