2012-04-07 63 views
1

我明白,也许使用“for”的代码可以清楚,但我想了解为什么这段代码不工作。 此外,该代码是2008年MIT OCW课堂练习的改编版本,其中允许使用的唯一函数是算术函数,如果,elif,else,print和while。 只是要指出,代码应该打印出前1000个素数。Python双while循环不工作,不能为什么

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. 第一次测试primecounter和primesupport之后小于1000,它进入循环。 然后,辅助支持值更改为1,因为3/2 = 1 由于primesupport大于0,它会进入第二个while循环。 如果条件为真(3%1 = 0),所以代码输入if,将primesupport更改为-1并将primesofar增加2(现在primesupport = -1,primesofar = 5) 这里有个问题,因为它不留印3,但让我们继续。 当它回到第二个时,它将收到一个False,因为-1不会大于0. 这将使代码测试第一次,并且由于primecounter没有更改,它将再次进入循环。 Primesupport现在将收到2(因为5/2 = 2) 它将进入第二个循环并遍历所有它直到else条件。 Primesupport将减1(primesupport now = 1),while循环将继续进入elif现在。 这将打印5 将primesofar增加到7 减少primesupport离开while循环并增加primecounter,返回到第一个循环并重新开始。 我承认,除了没有按预期打印的3之外,我无法看到我在这里犯了什么错误。希望你能指出我。

非常感谢大家的帮助,尤其是FallenAngel,John Machin,DiamRem和Karl Knechtel,他们指出了错误并展示了调试方法。

+0

定义“不工作” – 2012-04-07 08:14:19

+0

它卡住了,我必须ctrl + c它可能会结束一些无限循环 – 2012-04-07 08:17:25

+0

也,你确定你的缩进是正确的吗?更具体地说,是在第一个while循环内正确缩进的'primesupport = primesofar/2'行吗? – 2012-04-07 08:18:35

回答

1

我觉得这是问题:

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

+0

我想我现在看到一个问题,因为它不会打印3作为素数因为你写的东西,但是在if的第一行会设置主要支持到-1,不会结束第二个while循环之后离开if? – 2012-04-07 08:38:21

+0

yes结束第二个if但将primesofar再次设置为3,因此它重复的分割3/2 – diegueus9 2012-04-07 08:39:44

+0

不,Primesofar在if它仍然有3),并会在if(去5和重新开始)结束时增加2。除非if没有得到两个操作... – 2012-04-07 08:43:54

1
if primesofar%primesupport == 0: 
    primesupport=-1 

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

(虽然打破了一个循环的正确方法是使用break

+0

在这一点上,它必须离开if而没有改变primecounter,因为它发现的数字是不是素数,它只需要将素数增加2。也许if只处理第一行并且没有获得primesofar = primesofar + 2? – 2012-04-07 08:49:12

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,则执行该块,你primesofar增加2并开始新的质数检查...

+0

非常感谢您不仅仅是为了显示我的错误,而且还向我展示了一种调试方法。非常感激。 – 2012-04-07 09:36:17

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

+0

非常感谢您展示我的错误。把首要支持== 1条件首先解决了问题 – 2012-04-07 09:37:27

0

与您的代码的问题是,每一次primecounter到达1,要检查是否primesofar%的PrimeSupport == 0,它会一直这样做。所以你的程序永远不会进入elif和其他部分。因此素数计数器永远不会增加。所以这将是一个无限循环。

您可以通过将打印语句检查这一点,如果后primesofar%的PrimeSupport == 0:

if primesofar%primesupport == 0: 
    print primesofar 

您可以通过检查的PrimeSupport == 1纠正它,你检查primesofar%的PrimeSupport == 0之前:

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与+。你可以打印素数。打印语句将自动添加换行符。

+0

谢谢你指出我的错误。将首选支持条件更改为第一次检查可以解决我的问题。 – 2012-04-07 09:39:31