1

我知道也许使用“for”代码可能会很清楚,但我想了解为什么这段代码不起作用。此外,该代码是对 2008 年 MIT OCW 课程练习的改编,其中允许使用的唯一函数是算术函数,if、elif、else、print 和 while。需要指出的是,代码应该打印出前 1000 个素数。

print '2, '      #Print the prime 2 to set only odd primes.
primesofar=3     #Set 3 as the first prime
primecounter=1   #Mark 3 as the first prime to test until 1000, otherwise the while below should test to 1001
primesupport=1   #Create primesupport with a integer value
while primecounter<1000:
    primesupport=primesofar/2  #Create a support counter for test the prime. This counter only had to have the half value of the supposed prime, because we only need to try to divide by the primes that are lower than the half of the suppposed prime. In fact it would be better to test for values that are lower than the square root of the supposed prime, but we can't use square root operation yet.
    while primesupport>0:
      if primesofar%primesupport == 0:
        primesupport=-1       #If the remainer of the division is 0, the number isn't prime because it will have more than two divisors so we set primesupport as -1 to exit the while and increase the current primesofar to the next odd number.
        primesofar=primesofar+2
      elif primesupport==1:   #If primesupport is 1, we tested all the numbers below the half of the supposed prime which means the number is prime. So we print it, set the while exit and increase the number of primes counted and go to the next odd number.
        print primesofar+', '
        primesofar=primesofar+2
        primesupport=-1
        primecounter=primecounter+1
      else: 
        primesupport=primesupport-1

感谢您的快速响应,现在我认为代码中可能存在我看不到的中断。因此,我将尝试写下我认为代码应该执行的操作,以便您更容易指出我在哪里犯了错误。让我们开始吧:primesofar 收到 3;primecounter 接收 1 并且 primesupport 接收 1。第一个 while 测试 primecounter 并且由于 primesupport 小于 1000,它进入循环。然后,primesupport值变为1,因为3/2=1 由于primesupport大于0,进入第二个while循环。if 条件为真(3%1=0)所以代码输入 if,将 primesupport 更改为 -1 并将 primesofar 增加 2。(现在 primesupport=-1 和 primesofar=5)这里有问题,因为它离开不打印 3,但让我们继续。当它返回到第二个 while 时,它​​将收到一个 False,因为 -1 不大于 0。这将使代码测试第一个 while,并且由于 primecounter 没有更改,它将再次进入循环。Primesupport 现在将收到 2(因为 5/2=2)它将进入第二个循环并通过所有循环,直到出现 else 条件。Primesupport 将减一(primesupport now =1),while 循环将继续进入 elif。这将打印 5 增加 primesofar 到 7 减少 primesupport 以离开 while 循环并增加 primecounter,回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。这将使代码在第一个 while 中进行测试,并且由于 primecounter 没有更改,它将再次进入循环。Primesupport 现在将收到 2(因为 5/2=2)它将进入第二个循环并通过所有循环,直到出现 else 条件。Primesupport 将减一(primesupport now =1),while 循环将继续进入 elif。这将打印 5 增加 primesofar 到 7 减少 primesupport 以离开 while 循环并增加 primecounter,回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。这将使代码在第一个 while 中进行测试,并且由于 primecounter 没有更改,它将再次进入循环。Primesupport 现在将收到 2(因为 5/2=2)它将进入第二个循环并通过所有循环,直到出现 else 条件。Primesupport 将减一(primesupport now =1),while 循环将继续进入 elif。这将打印 5 增加 primesofar 到 7 减少 primesupport 以离开 while 循环并增加 primecounter,回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。Primesupport 现在将收到 2(因为 5/2=2)它将进入第二个循环并通过所有循环,直到出现 else 条件。Primesupport 将减一(primesupport now =1),while 循环将继续进入 elif。这将打印 5 增加 primesofar 到 7 减少 primesupport 以离开 while 循环并增加 primecounter,回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。Primesupport 现在将收到 2(因为 5/2=2)它将进入第二个循环并通过所有循环,直到出现 else 条件。Primesupport 将减一(primesupport now =1),while 循环将继续进入 elif。这将打印 5 增加 primesofar 到 7 减少 primesupport 以离开 while 循环并增加 primecounter,回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。回到第一个循环并重新开始。我承认,除了没有按预期打印的 3 之外,我看不出我在哪里犯了错误。希望你能指出我。

感谢大家的帮助,特别是 FallenAngel、John Machin、DiamRem 和 Karl Knechtel 指出错误并展示了调试方法。

4

5 回答 5

1

我放置了一些print语句,这是您的程序给出的输出:

primesupport 1
primesofar 5
primesupport 2
primesupport 1
primesofar 7
primesupport 3
primesupport 2
primesupport 1
primesofar 9
primesupport 4
primesupport 3
primesofar 11
primesupport 5
primesupport 4
primesupport 3
primesupport 2
primesupport 1
primesofar 13
primesupport 6
primesupport 5
primesupport 4
primesupport 3
primesupport 2
primesupport 1
primesofar 15
primesupport 7
primesupport 6
primesupport 5
primesofar 17
primesupport 8
primesupport 7
...

您的代码永远不会进入elif primesupport==1:块,所以primecounter永远不会增加......

用于测试的是:

while primecounter<2:
primesupport=primesofar/2
print 'primesupport %s' % primesupport
while primesupport>0:
    if primesofar%primesupport == 0:
        primesupport=-1 
        primesofar=primesofar+2
        print 'primesofar %s' % primesofar
    elif primesupport==1:
        print primesofar+', '
        primesofar=primesofar+2
        primesupport=-1
        primecounter=primecounter+1
        print 'primesofar %s' % primesofar
        print 'primesupport %s' % primesupport
        print 'primecounter %s' % primecounter
    else:
        primesupport=primesupport-1
        print 'primesupport %s' % primesupport

原因是,最终else块减少primesupport到 1,然后在下一个循环中,if primesofar%primesupport == 0:返回 true 并执行该块,增加primesofar2 并开始新的质数检查......

于 2012-04-07T09:06:16.757 回答
1

您需要在测试primesupport == 1之前进行测试,primesofar % primesupport == 0因为any_integer % 1始终为 0,并且您想要在primesupport == 1没有发生时执行的代码。

当你修复它时,你会发现它print primesofar+',不起作用......你应该能够自己修复它。

您可以部署的最基本的有效调试技术是 (1) 使用一小组数据,以便您可以理解正在发生的事情,并且您只需一支铅笔和一张纸就可以检查结果 (2)打印出正在发生的事情。

(1)while primecounter < 5:

(2) 在第二次之后,

print "sofar, support, count", primesofar, primesupport, primecounter

于 2012-04-07T09:07:56.527 回答
1
if primesofar%primesupport == 0:
    primesupport=-1

当代码到达这一点时,内部循环将被打破而不primecounter改变。代码将以相同的primecounter值重复相同的步骤,并且必然到达相同的点;没有办法打破外循环。

(尽管跳出循环的正确方法是使用break.)

于 2012-04-07T08:44:43.800 回答
1

我认为这是问题所在:

你被卡住了,因为 primesofar=3 和 python 3/2 = 1,所以如果 primesofar%primesupport == 0: 这是真的,因为 1%1 = 0 在 python 和代码中如果 primesofar 是 1+2,那么 primesofar 又是 3 并且你在永恒中从一段时间跳到另一个。

于 2012-04-07T08:30:54.590 回答
0

您的代码的问题在于,每次 primecounter 变为 1 时,您都在检查 primesofar%primesupport == 0,它总是会这样做。所以你的程序永远不会进入 elif 和 else 部分。因此素数计数器永远不会增加。所以这将是一个无限循环。

您可以通过在 if primesofar%primesupport == 0 之后放置一个打印语句来检查这一点:

if primesofar%primesupport == 0:
    print primesofar

在检查 primesofar%primesupport == 0 之前,您可以通过检查 primesupport==1 来纠正它:

print '2, '      #Print the prime 2 to set only odd primes.
primesofar=3     #Set 3 as the first prime
primecounter=1   #Mark 3 as the first prime to test until 1000, otherwise the while below should test to 1001
primesupport=1   #Create primesupport with a integer value
while primecounter<1000:
    primesupport=primesofar/2  #Create a support counter for test the prime. This counter only had to have the half value of the supposed prime, because we only need to try to divide by the primes that are lower than the half of the suppposed prime. In fact it would be better to test for values that are lower than the square root of the supposed prime, but we can't use square root operation yet.
    while primesupport>0:
        if primesupport==1:   #If primesupport is 1, we tested all the numbers below the half of the supposed prime which means the number is prime. So we print it, set the while exit and increase the number of primes counted and go to the next odd number.
            print primesofar
            primesofar=primesofar+2
            primesupport=-1
            primecounter=primecounter+1
        elif primesofar%primesupport == 0:
            primesupport=-1       #If the remainer of the division is 0, the number isn't prime because it will have more than two divisors so we set primesupport as -1 to exit the while and increase the current primesofar to the next odd number.
            primesofar=primesofar+2
        else: 
            primesupport=primesupport-1

此代码将为您打印 1000 个素数。

顺便说一句,你不能用 + 连接 str 和 int。你可以只打印素数。打印语句将自动添加换行符。

于 2012-04-07T09:20:57.073 回答