3

运行此 python 脚本时出现错误。

def thousandthPrime():
    count=0
    candidate=5 #candidates for prime no. these are all odd no.s Since starts at 5 therefore we find 998th prime no. as 2 and 3 are already prime no.s
    while(True):
        #print 'Checking =',candidate
        for i in range(2,candidate/2): #if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
            if(candidate%i==0):
                break
        if i==(candidate/2)-1: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
            count+=1
            print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate
        if(count==998):
            print 'The thousandth prime is',candidate
            break
        candidate+=2 # to go to the next odd number.

我收到此错误:

File "/home/.../xxx.py", line 19, in thousandthPrime
    if i==(candidate/2)-1: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
UnboundLocalError: local variable 'i' referenced before assignment

但是,如果我只用候选者替换候选者/2,我不会得到任何错误,尽管它增加了一些不必要的计算。

4

3 回答 3

6

您声明candidate为整数。因此candidate/2也是一个整数,特别是 2。那么你range(2, candidate/2)的 isrange(2, 2)什么都不是,所以i永远不会被初始化。您需要设置candidate=5.0使其浮动,一切都应该很好。

编辑 正如评论中所指出的,简单地重新定义candidate会给你一个类型错误,但这应该足以让你走上正轨。请注意,range(x, y)需要整数,您可能必须在使用除法或限制计算后再次转换为整数int()。此外,您可能想了解为什么math.sqrt提到该函数与素性测试有关

于 2013-11-13T18:32:53.040 回答
0

如果您逐步解决问题,则问题很简单:

>>> candidate=5
>>> candidate/2
2
>>> range(2, 2)
[]
>>> for i in []: print(i)
>>> i
NameError: name 'i' is not defined

你的循环是空的,所以你永远不会进入它,所以i永远不会被定义。

正如在其他地方的评论中指出的那样,您实际上只需要检查int(sqrt(candidate)),而不是candidate/2。但是如果你这样做,你仍然会遇到同样的问题:int(sqrt(5))仍然是2.


这意味着这个测试:

if i==(candidate/2)-1:

... 正在尝试访问尚未定义的变量。

但是如果你退后一步想想你真正测试的是什么,在伪代码中,它是这样的:

if I finished the loop without break:

Python 有一种内置的方式来表达这一点:else循环子句。

实际上,介绍此功能的教程部分break和循环continue语句和else子句有一个与您的示例非常相似的示例:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print n, 'equals', x, '*', n/x
...             break
...     else:
...         # loop fell through without finding a factor
...         print n, 'is a prime number'

else如果您在没有 a 的情况下完成循环,则将执行该子句break,这包括循环迭代器为空的情况。


因此,在您的代码中:

while(True):
    #print 'Checking =',candidate
    for i in range(2,candidate/2): #if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
        if(candidate%i==0):
            break
    else: # If none divide it perfectly, i will reach candidate/2-1 eventually. So, this is a prime number.
        count+=1
        print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate

如果您想了解比教程提供的更详细的工作原理,请参阅和else上的参考文档。whilefor

于 2013-11-13T19:11:03.883 回答
-1

变量的范围

这在这段代码中不是问题,即使i在其预期范围之外(在for构造内部)使用变量是不合适的,我应该在完成 for 循环后保持定义,前提是......

检查边缘情况

... for 循环应至少运行一次以声明某个变量的名称i

由于这不会发生,您会收到 UnboundLocalError。

快速解决

您可以通过在 for 循环之前声明 i 变量来解决此问题,以防它永远不会运行(一个简单的i = 2

推荐步骤

正如 Python Zen 本身所说的,显式优于隐式,通过使用不同的变量来获取你想要在 break 后保留的结果,你使这个值显式而不是隐式i循环后的变量。

例子:

def thousandthPrime():
    count = 0
    candidate = 5 # candidates for prime no. these are all odd no.s Since starts at 5 therefore we find 998th prime no. as 2 and 3 are already prime no.s
    while(True):
        # print 'Checking =',candidate
        useful_divider = 2
        for i in range(2, candidate / 2): # if any number from 2 to candidate/2 can divide candidate with remainder = 0 then candidate is not a prime no.
            if candidate % i == 0:
                useful_divider = i
                break
            if useful_divider == (candidate / 2) - 1: # If none divide it perfectly, useful_divider will reach candidate/2-1 eventually. So, this is a prime number.
            count+=1
            print 'No. of prime no.s found excluding 2 and 3 =',count, '--->',candidate
        # And so on...
        # ... and so on :)
于 2013-11-13T18:49:55.503 回答