【问题标题】:Python double while loop not working, can't figure whyPython双while循环不起作用,不知道为什么
【发布时间】:2012-04-07 08:11:02
【问题描述】:

我知道使用“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 之外,我看不出我在哪里犯了错误。希望你能指出我。

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

【问题讨论】:

  • 它卡住了,我必须按 ctrl+c 它可能会结束一些无限循环
  • 另外,你确定你的缩进是正确的吗?更具体地说,primesupport=primesofar/2 行是否在第一个 while 循环中正确缩进?
  • @Sensato sp 你调试了吗?哪个回路受到影响?循环变量的值是多少?
  • 或者primesupport=primesofar/2 不是整数?
  • @Kshitij:是的,缩进是对的,我只是在这里手动让它出现在代码框中。

标签: python


【解决方案1】:

我认为这是问题所在:

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

【讨论】:

  • 我想我现在看到了一个问题,因为它不会将 3 打印为素数,因为你写的内容,但在 if 的第一行会将 primesupport 设置为 -1,won' t 在离开 if 后结束第二个 while 循环?
  • yes 结束第二个 if 但又将 primesofar 设置为 3,因此它重复了除法 3/2。
  • 不,primesofar 在 if 中没有改变(它仍然有 3),它会在 if 结束时增加 2(转到 5 并重新开始)。除非 if 没有得到这两个操作...
  • 如果 primesofar 为 3 且 primesofar%primesupport = 1%1=0 代码从第一个 while 跳转到第二个 while 到 if 和第一个 while...
  • 现在我不确定我是否理解。我将尝试编写我认为代码会做的事情,如果您能指出我错的地方,我将不胜感激。对我来说,代码将进入第一个循环,primesofar=3 primecounter 并且支持=1。当 support=sofar/2 时,sofar 将得到 1。代码将进入 elif 并打印 3,增加 sofar,减少支持并增加 counter,留下第二个 while 并继续测试 5,我错了吗?跨度>
【解决方案2】:
if primesofar%primesupport == 0:
    primesupport=-1

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

(虽然跳出循环的正确方法是使用break。)

【讨论】:

  • 此时它必须离开 if 而不更改 primecounter 因为它找到的数字不是素数,它只需要将 primesofar 增加 2。也许 if 只处理第一行和没有得到 primesofar=primesofar+2?
【解决方案3】:

我放置了一些 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 并开始新的质数检查...

【讨论】:

  • 非常感谢您不仅展示了我的错误,还展示了调试方法。非常感谢。
【解决方案4】:

您需要在测试primesofar % primesupport == 0 之前测试primesupport == 1,因为any_integer % 1 始终为0,而​​您想要在primesupport == 1 时执行的代码不会发生。

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

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

(1)while primecounter &lt; 5:

(2) 第二次之后,

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

【讨论】:

  • 非常感谢您显示我的错误。把 primesupport == 1 条件先解决了问题
【解决方案5】:

您的代码的问题在于,每次 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。你可以只打印素数。打印语句会自动添加换行符。

【讨论】:

  • 感谢您指出我的错误。将 primesupport 条件更改为第一次检查解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多