Python 是否有大 numbers/lists 的问题,或者我的代码有问题?

Does Python have trouble with large numbers/lists, or is there something wrong with my code?

我有以下代码:

def main(n):
    sequence = []
    while n not in sequence:
        sequence.append(n)

        if n % 2 == 0:
            i = n / 2
        else:
            i = (n * 3) + 1
        n = int(i)

    print("Sequence length: " + str(len(sequence)-1))

n = int(input("Number: "))
main(n)

它从用户那里获取一个整数,然后计算该数字的“3x+1”(或 'Collatz')序列(有关详细信息,请参阅 http://www.ericr.nl/wondrous/index.html#part1)。然后显示序列的长度。

为了确保我的代码按预期工作,我将我的结果与 http://www.ericr.nl/wondrous/delrecs.html 上的 table 进行比较 'Delay' 列似乎是序列长度,并且 'N' 是输入的初始整数。我的代码为所有 'N' 值(我随机测试过)给出了正确的长度,最大为 1,899148,184679 (#92)。但是,对于 'N' 的下一个值(2,081751,768559,#93),它给出的长度为“385”(而不是“1437”)... [=29 上的所有值也是如此=](我已经测试过)比 table 上的要大 - 我的代码给出的答案比他们所做的要小得多。

Python 是否存在可能导致此行为的大数字问题,或者我的代码有问题?

我承认我不完全理解 'delay records',或者确实不完全理解该网页上的大部分信息。但是,即使我假设 'delay record' 只是此方法生成的序列的长度是错误的,但我的代码会计算相同的值直到该特定数字为止似乎很奇怪...

我正在使用 Python 3.8.10 以防相关。

  • 您需要使用 // 而不是 /
  • 错误发生在 number:19981441939834942,这是序列中的第 85 个索引。

测试代码:

x = 19981441939834942
print(19981441939834942 // 2)
print(int(19981441939834942 / 2)) # your code to calculate it.

测试结果:

9990720969917471 #correct result
9990720969917472 #wrong result

固定码:

def main(n):
    sequence = []
    while n not in sequence:
        sequence.append(n)

        if n % 2 == 0:
            n = n // 2 # you use `/` then convert to int, which may cause wrong result when n is a huge number.
        else:
            n = (n * 3) + 1
        # n = int(i)
    print("Sequence length: " + str(len(sequence)-1))

n = 2081751768559
main(n)

结果:

Sequence length: 1437

您遇到浮点错误。 “但我用的是整数!”我听到你说,好吧 Python 正在这条线上做浮点数除法:

i = n / 2

看似无伤大雅,但改成整数除法就解决了问题:

i = n // 2

经过数百个值后,其中一个除法给您一个错误,该值比实际整数值小一些 epsilon,然后在您调用 int(n).

时向下舍入

编辑:在仔细检查我的最后一点以找到失败的值之后,我不太正确。实际发生的情况是,由于 Pythons BigInt 实现,整数除法始终准确,但浮点数除法并非如此,因为它仍然使用常规浮点数来提高速度。如果您的数字足够大,那么根本就没有足够的字节来准确存储数字,这将导致舍入错误。

有问题的号码是19981441939834942。使用整数除法得到 9990720969917471,而浮点除法得到 9990720969917472.0.

这在你使用的任何语言中都会是一个问题(除了大多数其他语言不允许你不小心对整数使用浮点除法),所以一定要使用整数除法!