【问题标题】:Python: "long int too large to convert to float" when checking (really big) prime numbersPython:检查(非常大的)素数时“long int太大而无法转换为float”
【发布时间】:2018-05-01 19:57:05
【问题描述】:

我试图从这个答案中实现第一个 is_prime 函数: https://stackoverflow.com/a/17298131/6208280

# for large numbers, xrange will throw an error.
# OverflowError: Python int too large to convert to C long
# to get over this:

def mrange(start, stop, step):
    while start < stop:
        yield start
        start += step

# benchmarked on an old single-core system with 2GB RAM.

from math import sqrt

def is_prime(num):
    if num == 2:
        return True
    if (num < 2) or (num % 2 == 0):
        return False
    return all(num % i for i in mrange(3, int(sqrt(num)) + 1, 2))

但我在测试大量数字时遇到了一点问题。

对于非常大的数字,我收到溢出错误:long int too large to convert to float

我检查了浮动的最大值:

sys.float_info.max
1.7976931348623157e+308

对于is_prime(10**308),一切正常...但例如is_prime(10**309) 会出现这个溢出错误(因为float max?)。

这是否意味着 1.7976931348623157e+308 是这种 is_prime() 函数的限制,或者是否有任何解决方案可以使用 is_prime() 函数检查更高的数字?

在我看来,诸如“使用小数”之类的解决方案并不能真正解决问题,因为素数检查功能需要的精度不足?

【问题讨论】:

  • 这意味着(sys.float_info.max - ϵ) ** 2 是极限,因为您正在调用sqrt(num)。有“整数平方根算法”可以避开任何使用浮点数,可能像this one
  • 您有没有想过要检查一个 308 位数字是否为质数需要多少操作,以及需要多长时间?对于 20 位数字,您的函数已经太慢了,更不用说 300 位数字了。

标签: python algorithm int precision primes


【解决方案1】:

如果您需要浮点数的唯一原因是能够执行int(sqrt(num)),您可以找到一个相当有效的intsqrt 函数并改用它。有关一些想法,请参阅this question,以及从接受的答案链接的博客文章。


或者您可以更改您的代码,使其根本不需要sqrt。例如,您可以使用测试lambda i: i*i &lt;= numtakewhile 而不是以int(sqrt(num))+1 结尾的范围。或者,既然你已经有了mrange 函数:

def sqrmrange(start, sqrstop):
    while start*start < sqrstop:
        yield start
        start += step

或者,如果你不需要它是单行的,你可以写一些不那么抽象的东西(也许更有效?)。 (但实际上,任何intsqrt 都可能比最好的**2 测试更快,因为您只需在循环开始时执行一次intsqrt,而不是每次循环。)


或者,如果你真的想保持这种结构,你可以使用decimal。你说:

在我看来,诸如“使用小数”之类的解决方案并不能真正解决问题,因为素数检查功能需要的精度不足?

但这是不对的。使用 float 意味着您天生就被限制在 52 位精度,如果在您溢出之前很久就会出现问题。使用decimal 意味着您可以获得尽可能多的精度,即使是默认的 30 位也已经远远超过 52 位。例如:

>>> float(10**20) == float(10**20)+1
True
>>> Decimal(10**20) == Decimal(10**20)+1
False

(事实上,由于您是从一个巨大的int 构建Decimal,它会自动扩展以跟踪int 所需的尽可能多的数字……但您仍然需要设置调用 sqrt 之前的精度。)

以编程方式计算和设置操作所需的精度可能很复杂,但在这种情况下,它非常简单。更大的问题是非常大的Decimals 比非常大的整数要慢很多。

【讨论】:

    猜你喜欢
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多