Python 中的 Collatz 序列。有什么改进吗?[已结束]

Collatz Sequence in Python. Any improvements? [closed]

提问人:babuindhaka 提问时间:3/15/2023 最后编辑:babuindhaka 更新时间:3/16/2023 访问量:110

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

8个月前关闭。

我在 Python 编程方面相对较新,这是我在 Stack Overflow 中的第一篇博文。有人可以告诉我这段代码是否是 Python 中 Collatz 序列的完整证明。谢谢

def collatz(number):
    while True:
        if number % 2 == 0:
            number = number // 2
        else:
            number = 3 * number + 1
        print(number)
        if number == 1:
            break
        

while True:
    try:
        number = int(input("Enter a positive non-zero integer: "))
        if number <= 0:
            print("Please enter a positive non-zero integer.")
        else:
            collatz(number)
            break
    except ValueError:
        print("Please enter a valid integer.")

为了检查,我尝试使用负整数、0 和 1 以及字符串作为输入。

蟒蛇 科拉茨

评论

1赞 Caridorc 3/15/2023
这更像是一个数学问题,你已经用这段代码提供了强有力的证据来反对这个猜想,但所有数字都需要有一个证明
4赞 InSync 3/15/2023
该程序无法证明猜想,因此不是“证明”。这个问题更适合在代码审查中。
4赞 MSalters 3/15/2023
我怀疑这个问题是模棱两可的。这是否试图问这是“完全证明”(即数学上完整的证明)还是“万无一失的证明”,即对错误输入的鲁棒性?
0赞 Kelly Bundy 3/16/2023
@MSalters 我也是这么想的,看起来他们不会回答这个问题,但他们的评论说“我只是想知道代码是否正常”听起来确实是万无一失的。有趣的是,所有热心的回答者都谈到了“完整的证据”。

答:

0赞 Harmen Dijkstra 3/15/2023 #1

问题确实是什么模糊。该代码永远不可能成为 Collatz 推定的数学证明。但是,如果你的意思是,这个代码是否可以用来测试某个数字是否成立 Collatz 的假设。是的,您的代码是正确的,可以测试这一点。这个假设是一个简单的循环,你做对了。

从理论上讲,你可以让它更紧凑、更快(但请注意,代码已经足够快了)。其他小改进包括:

def collatz(number):
    while number != 1:
        if number & 1 == 0:
            number >>= 1
        else:
            number = 3 * number + 1
        print(number)

while True:
    try:
        number = int(input("Enter a positive non-zero integer: "))
        if number <= 0:
            print("Please enter a positive non-zero integer.")
        else:
            collatz(number)
            break
    except ValueError:
        print("Please enter a valid integer.")

这使用按位运算符:&(用于检查偶数),删除 if 语句并使用位移运算符:>> 对于巨大的数字,您可能不想打印这些数字

评论

0赞 babuindhaka 3/15/2023
谢谢你的回答。我已经运行了你的代码。如果输入为 1,则不显示任何内容。对不起,误会了。作为 python 的新手,我只是想知道代码是否正常。
1赞 P i 3/15/2023 #2

一些提示。

首先,你应该意识到,通过尝试大量起始数字并证明每个起始数字都达到 1,你永远无法获得证明(所有起始数字最终都达到 1)。你只会实现一个强烈的期望,即它确实适用于所有正整数。

您可能希望返回输入达到 1 所花费的步数。

然后,您可以打印以检查它是否正常工作。[collatz(k) for k in range(20)]

如果到目前为止一切顺利,您可能想尝试 计时 ,这将允许您调整算法的速度(如果您愿意的话)。[collatz(k) for k in range(10_000)]

我会把核心代码写得更像:

def collatz(k:Int):
    assert k > 0
    counter = 0
    while k != 1:
        k = k // 2 if k % 2 == 0 else 3 * k + 1
        counter += 1
    return counter

最后,您可能有兴趣使用类似的东西来实现大规模(>>100 倍)的加速。你会从中学到的一件事是,Python 并不适合紧密的低级循环。当你.如果你用 C 语言编写相同的代码,你会注意到性能差异很大。像这样的技术可以达到接近C的速度。numbau += 1numba

评论

0赞 babuindhaka 3/15/2023
谢谢你的回答。我刚刚开始学习 python 编程。希望将来使用 numba(我刚刚用谷歌搜索过它是什么)。
0赞 Alain T. 3/16/2023 #3

而不是 while True,可以使用一个条件,即当/如果猜想错误时可以退出。有两种方法可以证明这个猜想是错误的:1)序列循环到以前看到的数字2)它逐渐扩展到无穷大,而不会收敛回1。

对于第二个,您无能为力(除非您可以证明可以预先计算最大步长值的最大迭代次数)。对于第一个,您可以随时将数字存储在一个集合中,并根据该集合检查新值。

def collatz(number):
    seen = set()
    while number != 1 and number not in seen:
        seen.add(number)
        if number % 2:
            number = 3 * number + 1
        else:
            number //= 2            
        # print(number)
    return number == 1    # true if 1 reach, False otherwise