循环重复/卡住?Python 3.2

1 投票
3 回答
866 浏览
提问于 2025-04-17 08:20

我正在尝试写一个用来实现埃拉托斯特尼筛法的Python脚本。我已经完成了大部分工作,但当我让程序测试每个数字是否是小于输入值平方根的某个质数的倍数时,一切都很顺利。但是,当我尝试删除一个倍数时,它能正常工作,直到它试图删除6两次……我查看了我的代码,但就是找不到原因。我对Python还比较陌生,所以如果能得到帮助,我会非常感激!--- 注意,由于SOF的代码块格式,我的代码缩进有点问题:

import math, os, threading

global iswhole
global tdprime

def iswhole(x):
if x%1 == 0:
    return True
else:
    return False

def tdprime(x):
prime = True
n = 2

while n < x:
    if iswhole(x/n) == True:
        return False
        prime = False
        n = x
    else:
        n += 1

if prime == True:
    return True

number = 0

while number != 1:

number = int(input("Enter number to calculate all primes up to:  "))
number_range = range(1,number+1)
sqrt = math.sqrt(number)
rsqrt = round(sqrt)
thelist = []
tsl = []

for num in range(1,rsqrt):
    if tdprime(num) == True:
        tsl.append(num)
tsl.remove(1)

for x in number_range: ## Making the List
    thelist.append(x)
    ## Note it's " Key: Value " in dictionaries

print(tsl)
print("thelist: ",thelist)
print("Square root of input = ",sqrt)
print("Rounded Square root of input = ",rsqrt)
print()

for x in thelist: ## Testing each number in thelist

    multiple = False

    for y in tsl: ## Each prime number under √number

        if iswhole(x/y):
            print(x) ## If the current number in thelist divided by one of the prime numbers under √number is a whole
            thelist.remove(x)## Remove the current number which isn't a prime
            thelist.sort()
            multiple = True ## Make multiple true so it doesn't print (could remove the multiple stuff and other if function, kind of pointless function now)

    if multiple == False:
        print("Prime! ",x)


print(thelist)

3 个回答

1

我看到这里有个问题:

for x in thelist: ## Testing each number in thelist

    multiple = False

    for y in tsl: ## Each prime number under √number

        if iswhole(x/y):
            print(x) ## If the current number in thelist divided by one of the prime numbers under √number is a whole
            thelist.remove(x)## Remove the current number which isn't a prime
            thelist.sort()

你在遍历 thelist 的时候调用了 thelist.remove(x)thelist.sort()。在 Python 中,通常不建议在遍历一个列表的时候去修改它。这样做会让内部处理遍历的机制感到困惑,可能会出现一些奇怪的情况,比如跳过某些元素,或者处理同一个元素两次,或者其他奇怪的行为。

1

我有点担心你的 iswhole() 函数:

def iswhole(x):
    if x%1 == 0:
        return True
    else:
        return False

顺便说一下,这个函数可以简化成 return (x%1 == 0),这样就可以省去 return Truereturn False 的部分。

浮点数是个奇怪的东西:

>>> 10.0%1
0.0
>>> (10.1 * 10)%1
0.0
>>> (10.01 * 100)%1
0.0
>>> (10.001 * 1000)%1
0.0
>>> (10.0001 * 10000)%1
0.0
>>> (10.00001 * 100000)%1
0.0
>>> (10.000001 * 1000000)%1
0.0
>>> (10.0000001 * 10000000)%1
0.0
>>> (10.00000001 * 100000000)%1
1.1920928955078125e-07

对于像 6 这样的输入,似乎不会有问题,但对于更大的输入,这可能会变得麻烦。比较浮点数是个麻烦事

关于 6 的问题,我建议你用一个 数组 来代替可变列表来存储数据。数组不需要排序(你程序里有 sort() 这个函数,感觉像是在掩盖某种错误),而且从列表中间删除元素通常会非常耗费资源。(那个 sort 函数基本上意味着你的性能会很差。对于小数据量来说没什么大不了,但如果你试试1000000作为起点,就会发现问题了。)在数组中设置元素为 10 通常比可变列表便宜得多。

2

你的代码可以通过以下几点大大简化:

  • 你可以根据需要随时生成到某个数字 n 的所有数字,不需要提前计算好并存储在列表里。

  • 2 是唯一的偶数质数,所以你只需要测试奇数。

  • 所有数字都可以完全分解成质因数,而且这种分解是唯一的(这被称为 算术基本定理)。这意味着你只需要尝试用之前计算出的质数去除其他数字——其他数字至少会被其中一个质数整除(否则它们自己就是质数)。

可以尝试这样的思路:

stop = int(input("Enter number to calculate all primes up to: "))

primes = []

for n in range(3, stop, 2): # Step by two each time
    was_prime = True # Needed to break out of nested loop
    for p in primes:
        if n % p == 0: # A prime divides n
             was_prime = False
             break # No need to continue
    if was_prime:
        primes.append(n)

print(primes) # You can insert the number 2 here if you like

另外,请注意空格和缩进。在 Python 中,如果你的空格不对,不仅难以阅读,还会导致运行时错误。

撰写回答