我试图使用递归来查找数字是否为2的幂。但是,我似乎无法找到正确的解决方案。这是我到目前为止所尝试的内容:
def is_power(n):
n = n/2
if n == 2:
return True
elif n > 2:
is_power(n)
else:
return False
if is_power(32):
print 'yes'
else:
print 'no'
因为' 32'是2的幂,我希望我的代码返回'是'作为输出。但是,代码输出“没有”'代替。我的代码似乎有什么问题?
答案 0 :(得分:22)
由于我已经在这里得到了一个接受的答案,我将用这个解释一下为什么你的方法不好:
它在python中使用递归。 Python需要为每个调用打开一个堆栈帧,因此对于非常大的数字,这将是解决此问题的一种不好的方法。对于非常大的整数,它甚至会失败。
我甚至不认为递归非纯函数式语言就像python一样直观。有一百万种更简单的方法可以做到这一点;例如,while
循环:
n = int(n)
while n>1:
if n/2 != n/2.0: #compare integer division to float division
return False
n = n/2
return True
通过实现计算机上整数的存储结构是:二进制,可以巧妙地完成对两个的权限的检查。因此,您可以在1
的二进制表示中计算二进制int
:
return bin(n).count('1') == 1
也会奏效。当然,这意味着python在内部将整数转换为字符串,这会浪费大数字的内存。所以你不妨
power_of_2 = 1
while power_of_2 <= n:
if power_of_2 == n:
return True
power_of_2 *= 2
return False
只需将您的数字与两个所有较小或相等的幂相比较。 (当然可能需要更长时间并且使用更多内存,因为你的python解释器必须解释python而不是仅仅将你的整数转换为C中的字符串,但这是关于算法原理的,对吧?)这样,你就不会# 39; t需要保留内存,以便在二进制表示中计算出1的出现次数。
当然,有一个解决你的问题的单线程,我从C / C ++的things I've learned写作中得到它:
bool(n and not (n&(n-1)))
要解释n and not (n&(n-1))
:n
为真{if} n != 0
,否则将错误地认定为2的幂。
对于not (n&(n-1))
:n&(n-1)
检查某些内容是否不是2的幂,所以我们必须将其反转。 &
是按位&#34;和&#34;运营商。要理解n & (n-1)
,假设n
是2的幂,让我们说8
。所以n-1 == 7
,因此
8|0b1000
7|0b0111
--------
&|0b0000
如您所见,对于2的所有权力,n&(n-1)
为0
,其评估为False
。对于所有2的非幂,在减去1
时,您不会反转所有位,因此n&(n-1) != 0
会计算为True
。
答案 1 :(得分:4)
elif n > 2:
is_power(n)
缺少return
:
def is_power(n):
n = n/2
if n == 2:
return True
elif n > 2:
return is_power(n)
else:
return False
因此,is_power
的“第一”级别不会返回任何内容(或None
,具体取决于您的检查方式),这会导致no
的输出。
@kaveman正确地指出is_power(2)
会产生错误的结果。
你可以通过在elif
子句中减半2来解决这个问题:
def is_power(n):
if not n == int(n):
return False
n = int(n)
if n == 1:
return True
elif n > 2:
return is_power(n/2.0)
else:
return False
编辑:@will指出我正在将python2与python3部门混在一起。使用/2.0
修复了该问题。此外,在对该问题的评论中,他指出1是2的幂。检查==1
而不是==2
修复该问题。另外,我添加了一个int
强制转换,这对于2次检查的功能来说不是必需的(因为,毕竟IEEE754浮点数基数为2,因此2的幂可以准确表示),但对于非2个基数,这将使代码可移植。
答案 2 :(得分:3)
上面提供的答案是错误。
是的,它适用于2的幂,但它也会产生许多误报 - 因为你使用的是整数除法 - 因为你使用的是python 2.7。
如果您使用的from __future__ import division
改变了/
的行为,它会起作用 - 但这会改变整个程序的行为,这可能不是您想要的。
例如:
print 33/2 # 16
print 32/2 # 16
但是,使用from __future__ import division
输出会更改为正确(或至少更直观)的结果 - 要获得原始整数数学行为,您需要使用//
代替(如在python3中)。 / p>
所以正确答案更像是这样:
def is_power(n):
n = n/2.0
if n == 2:
return True
elif n > 2:
return is_power(n)
else:
return False
请注意开头的 n= n/2.0
。
您需要测试您的代码是否适用于多个测试用例,而不仅仅是您想要特定结果的测试用例。
或者,我会选择这样的东西:
def is_power(n):
if n == 2:
return True
elif n%2 != 0:
return False
else:
return is_power(n/2.0)
答案 3 :(得分:2)
虽然这并没有直接回答你的问题,但实现这一目标的最快方法是
def is_power(n):
return ((n & (n - 1)) == 0) and n != 0
虽然马库斯的上一篇文章已经涵盖了这一点,但有一点&#39;更多解释可能有所帮助。每个数字的二进制表示和(数字-1)共享至少一个1位,除非该数字是2的幂。此外,所有负数共享前导位,因此被此方法排除。
唯一的例外是数字0,它不与前一个数字-1共享位,并且可能不被视为2的幂。因此需要进行明确的检查。
数字的二进制表将清楚地说明这一点。
> Dcml Binary 5bit
> -15 10001
> -14 10010
> -13 10011
> -12 10100
> -11 10101
> -10 10110
> -9 10111
> -8 11000
> -7 11001
> -6 11010
> -5 11011
> -4 11100
> -3 11101
> -2 11110
> -1 11111
> 0 00000
> 1 00001
> 2 00010
> 3 00011
> 4 00100
> 5 00101
> 6 00110
> 7 00111
> 8 01000
> 9 01001
> 10 01010
> 11 01011
> 12 01100
> 13 01101
> 14 01110
> 15 01111
> 16 10000
此签名数字表示法中的负数不会满足条件,因为它们共享最高有效位为1.数字0将满足条件为0&amp;(any_other_number)== 0.如果您需要实现此非常大数字你最好使用here on line 60或numpy更改dtype。此外,this guide讨论可能有助于大型数组/数字的按位运算速度。
答案 4 :(得分:1)
这是我针对某个函数的解决方案,该函数检查哪个数字是另一个数字的基数:
def is_power_of(number, base):
# when number is smaller than base.
if base <= 1:
return False
elif number < base:
return False
elif number > base:
# keep dividing number by base.
return is_power_of(number/base, base)
else:
return True
答案 5 :(得分:0)
''''
Power check if a number is a power of 2
Negative numbers are not allowed
'''
import math
def is_power_of_two(num):
"""
:type num: object
"""
try:
x=0
x = math.log10(num)/math.log10(2)
return 2 ** x == num
except ValueError:
exit()
答案 6 :(得分:0)
这会提供一些信息,
counter = 0
def powoftwo(n):
global counter
counter+=1
if n%2 != 0:
return "Given Number %s is not Power of 2!"%g
else:
if n==2:
return "yes give number %s = 2**%s is power of 2!"%(g, counter)
return powoftwo(n/2)
g = 1024
print powoftwo(g)
yes give number 1024 = 2**10 is power of 2!
答案 7 :(得分:0)
您可以只使用数学库的功能
import math
def isPowerOfTwo(n):
if n <= 0:
return False
res = int(math.log(n) / math.log(2))
return 2 ** res == n
答案 8 :(得分:0)
晚了,但是,另一种方式:
import math
def is_power_of_2(x):
n = math.log(abs(x), 2)
return n == int(n)