繁体   English   中英

查找是否n! +1是一个完美的正方形

[英]Finding if n! + 1 is a perfect square

我正在尝试编写一个程序来查找介于0到100之间的n,即n! +1是一个完美的正方形。 我正在尝试执行此操作,因为我知道只有三个,所以这是对我的Python能力的测试。

请参阅Brocard的问题

math.sqrt始终返回一个float ,即使该float恰好是4.0 正如文档所说,“除非另有明确说明,否则所有返回值都是浮点数”。

因此,您对type(math.sqrt(x)) == int将永远是不正确的。

您可以尝试通过检查float是否代表整数来解决此问题,如下所示:

sx = math.sqrt(x)
if round(sx) == sx:

甚至还有一个内置方法可以做到这一点:

if sx.is_integer():

但是请记住, float值并不是实数的完美表示,并且始终存在舍入问题。 例如,对于太大的数字, sqrt可能四舍五入为整数,即使它实际上不是理想的正方形。 例如,如果math.sqrt(10000000000**2 + 1).is_integer()True ,即使该数字显然不是理想的平方。

我可以告诉您这在您的价值观范围内是否安全,但是您可以说服自己吗? 如果不是,您不应该仅仅假设它是。

因此,有没有一种方法可以检查不受float路线问题的影响? 当然,我们可以使用整数算法来检查:

sx = int(round(math.sqrt(x)))
if sx*sx == x:

但是,正如Stefan Pochmann指出的那样,即使这种检查是安全的,这是否意味着整个算法也是如此? 没有; sqrt本身可能已经舍入到失去整数精度的程度。

因此,您需要一个确切的sqrt 可以通过使用decimal.Decimaldecimal.Decimal以极大的配置精度做到这一点。 这将需要一些工作和大量内存,但这是可行的。 像这样:

decimal.getcontext().prec = ENOUGH_DIGITS
sx = decimal.Decimal(x).sqrt()

但是ENOUGH_DIGITSENOUGH_DIGITS 那么,您到底需要多少个数字才能代表100!+1

所以:

decimal.getcontext().prec = 156
while n <= 100:
    x = math.factorial(n) + 1
    sx = decimal.Decimal(x).sqrt()
    if int(sx) ** 2 == x:
        print(sx)
    n = n + 1

如果您考虑一下,有一种方法可以将所需的精度降低到79位,但我将其留给读者练习。


您大概应该解决此问题的方法是使用纯整数数学。 例如,您可以通过使用牛顿方法来找出整数是否为对数时间的平方,直到您的逼近误差足够小以至于只需检查两个边界整数即可。

对于非常大的数字,最好完全避免使用浮点平方根,因为这样会遇到太多的精度问题,甚至不能保证您在正确答案的1整数值以内。 幸运的是,Python本机支持任意大小的整数,因此您可以编写一个整数平方根检查函数,如下所示:

def isSquare(x):
    if x == 1:
        return True
    low = 0
    high = x // 2
    root = high
    while root * root != x:
       root = (low + high) // 2
       if low + 1 >= high:
          return False
       if root * root > x:
          high = root
       else:
          low = root
    return True

然后,您可以像这样通过0到100的整数进行运算:

n = 0
while n <= 100:
    x = math.factorial(n) + 1
    if isSquare(x):
        print n
    n = n + 1

这是另一个仅处理整数的版本,通过增加2的递减幂来计算平方根,例如intsqrt(24680)将被计算为128 + 16 + 8 + 4 + 1。

 def intsqrt(n):
    pow2 = 1
    while pow2 < n:
        pow2 *= 2
    sqrt = 0
    while pow2:
        if (sqrt + pow2) ** 2 <= n:
            sqrt += pow2
        pow2 //= 2
    return sqrt

factorial = 1
for n in range(1, 101):
    factorial *= n
    if intsqrt(factorial + 1) ** 2 == factorial + 1:
        print(n)

math.sqrt返回的数字永远不是int,即使它是整数。 如何检查浮点值是否为整数

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM