依赖于任何浮点计算(math.sqrt(x)或x ** 0.5)的问题是,你不能真正确定它是精确的(对于足够大的整数x,它不会,甚至可能溢出)。幸运的是(如果一个人不急着;-)有很多纯粹的整数方法,如下面的…:
def is_square(apositiveint):
x = apositiveint // 2
seen = set([x])
while x * x != apositiveint:
x = (x + (apositiveint // x)) // 2
if x in seen: return False
seen.add(x)
return True
for i in range(110, 130):
print i, is_square(i)
提示:它是基于“巴比伦算法”的平方根,见wikipedia.它可以为任何正数,你有足够的内存,计算进行完成;-)。
编辑:让我们看一个例子…
x = 12345678987654321234567 ** 2
for i in range(x, x+2):
print i, is_square(i)
这打印,根据需要(并在合理的时间量,也;-):
152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False
在你提出基于浮点中间结果的解决方案之前,请确保它们在这个简单的例子上正确工作 – 这不是那么难(你只需要一些额外的检查,如果sqrt计算有点偏离),只需要一个小心。
然后尝试用x ** 7和找到聪明的方式解决你会得到的问题,
OverflowError: long int too large to convert to float
你必须越来越聪明,因为数字不断增长,当然。
如果我很匆忙,当然,我会使用gmpy – 但是,然后,我显然有偏见;-)。
>>> import gmpy
>>> gmpy.is_square(x**7)
1
>>> gmpy.is_square(x**7 + 1)
0
是啊,我知道,这只是那么容易,感觉像欺骗(有点我对Python的感觉一般; – ) – 没有聪明,只是完美的直接性和简单性(和gmpy的情况下,纯粹的速度; – )…