我怎么能检查一个数字是一个完美的广场?
我怎么能检查一个数字是一个完美的广场?
现在,速度不用担心,只是在工作。
依赖任何浮点运算( 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)
提示:它基于平方根的“巴比伦算法”,参见维基百科。 它适用于任何正数,因此您有足够的内存用于计算以继续完成;-)。
编辑 :让我们看一个例子...
x = 12345678987654321234567 ** 2
for i in range(x, x+2):
print i, is_square(i)
根据需要(和合理的时间量)打印;-):
152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False
请您根据浮点中间结果提出解决方案之前,要确保他们在这个简单的例子正常工作-这并不难 (你只需要一些额外的检查的情况下,计算出的平方根是有点过),只是需要一点护理。
然后尝试使用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的情况下,速度很快; - )...
使用牛顿的方法快速调入最接近的整数平方根,然后将其平方,看看它是否是你的数字。 见isqrt。
由于在处理浮点计算时(例如这些计算平方根的方法),您永远无法依赖精确比较,因此不太容易出错的实现
import math
def is_square(integer):
root = math.sqrt(integer)
if int(root + 0.5) ** 2 == integer:
return True
else:
return False
想象一下integer
是9
。 math.sqrt(9)
可能是3.0
,但也可能是2.99999
或3.00001
类的东西,所以将结果直接平方并不可靠。 知道int
取最低值,首先将float值增加0.5
意味着如果我们处于float
仍然具有足够精细分辨率以表示数字的范围内,我们将获得我们要查找的值我们在看。