【问题标题】:Python: attempting a recursive primality test with a try-except-else statementPython:尝试使用 try-except-else 语句进行递归素数测试
【发布时间】:2016-02-12 01:32:01
【问题描述】:

我一直在学习递归和错误处理。我很难理解为什么我的素数测试不起作用:

def is_prime4(n):
    """Recursive primality test"""
    try:
        div
    except NameError:
        div = n - 1
    else:
        div = div - 1
    while div >= 2:
        if n % div == 0:
            print 'No, {number} is not prime because it is divisible by {div}.'.format(number = n, div = div)
            return False
        else:
            return is_prime4(n)
    else:
        print 'Yes, {number} is prime indeed.'.format(number = n)
        return 'True'

is_prime4(2)
is_prime4(3)
is_prime4(4)

我认为问题出在 try-except-else 语句中,但我很难理解原因。

感谢您的帮助。

【问题讨论】:

  • 主要问题是您的代码中有语法错误。 try: div 不是合法序列。你需要一个命令,而不是一个表达式。
  • 我不确定我是否理解。 try 用于测试div 的存在,并在必要时对其进行初始化。据我所知,that part is working.
  • 您使用的是哪个 Python 版本?我在2.7上,一开始就失败了。也许你有更高级的东西;我以前没有见过这种用法,所以我感谢你提供的链接。
  • 另外,使用这种异常语法有什么特别的原因吗?大多数语言(包括 Python)的异常真的很慢。
  • 素数测试不适合递归解决方案。你所做的只是低效地实现一个循环。

标签: python recursion primes


【解决方案1】:

递归深度问题是因为 div 对于每个本地上下文都是新的。它不是一个全局变量。每次进入例程时,都会得到一个新的上下文,包括一组新的局部变量。因此,如果您有 n = 7,则每次调用都会设置 div = 6。你永远不会改变它,所以你会进入无限递归。

您需要采用更清洁的解决方案,例如其他海报所建议的解决方案。


这是您的代码,使用全局 div。请注意,您必须在每次完成后重置它......不知何故......它很丑......

div = -1

def is_prime4(n):
    """Recursive primality test"""
    global div
    if div < 0:
        div = n - 1
    else:
        div = div - 1

    while div >= 2:
        if n % div == 0:
            print 'No, {number} is not prime because it is divisible by {div}.'.format(number = n, div = div)
            div = -1
            return False
        else:
            return is_prime4(n)
    else:
        print 'Yes, {number} is prime indeed.'.format(number = n)
        div = -1
        return True

    for i in range(20):
        is_prime4(i)

输出:

Yes, 0 is prime indeed.
Yes, 1 is prime indeed.
Yes, 2 is prime indeed.
Yes, 3 is prime indeed.
No, 4 is not prime because it is divisible by 2.
Yes, 5 is prime indeed.
No, 6 is not prime because it is divisible by 3.
Yes, 7 is prime indeed.
No, 8 is not prime because it is divisible by 4.
No, 9 is not prime because it is divisible by 3.
No, 10 is not prime because it is divisible by 5.
Yes, 11 is prime indeed.
No, 12 is not prime because it is divisible by 6.
Yes, 13 is prime indeed.
No, 14 is not prime because it is divisible by 7.
No, 15 is not prime because it is divisible by 5.
No, 16 is not prime because it is divisible by 8.
Yes, 17 is prime indeed.
No, 18 is not prime because it is divisible by 9.
Yes, 19 is prime indeed.

【讨论】:

  • 谢谢。现在我明白了。在问这个问题之前,我已经有了 3 个工作版本的素数测试。我的目标是探索以这种方式执行此操作的可能性,使用 try-except-else 和只有一个函数参数。
  • 啊哈!好的。如何将 div 设为全局,但在外部将其初始化为 -1 以表示“未使用”?我怀疑这违反了你正在尝试做的事情。
  • 我宁愿不使用全局变量,但不可否认,这也是我尝试过但无法正常工作的方法。每个值都作为素数返回...
  • 您有一个信息问题,那么:您重复的步骤需要“候选素数”以及要测试的红利。这是每次迭代都需要的两个不同的参数;您必须以某种方式提供该信息。正如我所看到的,将其减少为单个参数的唯一方法是以某种方式将两个数据打包到一个对象中。例如,传递一个 2 元组。我知道,这是捆绑语义,而不是解决优雅的问题。我相信递归本质上打破了优雅所需的连续性。
【解决方案2】:

您基本上是在尝试执行while 循环并递归调用该函数。它可以工作,但不是这样。我建议使用循环或递归。

你的代码还有另外两个缺点:你的递归永远不会结束,如果它结束了你的循环永远不会结束。

循环(终止)的一个例子是:

def is_prime4(n):
    """Recursive primality test"""
    div = n # very inefficient because one would only need to start at int(sqrt(n))
    while div > 2:
        div -= 1 # So that the loop terminates in the end.
        if n % div == 0:
            print('No, {number} is not prime because it is divisible by {div}.'.format(number = n, div = div))
            return False
    else:
        print('Yes, {number} is prime indeed.'.format(number = n))
        return True

is_prime4(2)
is_prime4(3)
is_prime4(4)

【讨论】:

  • 谢谢,但我的目标是通过递归来实现。我已经有了一个带有 for 循环和 while + 第二个参数的函数的工作版本。我应该从一开始就更清楚地说明这一点。
  • 请注意,代码只是为了强调我的 cmets 关于终止。同样的论点也适用于递归。所以你想要一个只接受一个参数的递归函数?
  • 没错。我可以用 2 个参数来做,但我不能用一个来做。
  • 我无法想到只有一个参数,因为您需要使用全局变量,或者一个参数可能是tuplelist。这就像在欺骗自己:“我的函数只需要一个参数,还需要一个全局变量”。 :-)
  • 我一直在为这个问题苦苦挣扎,以为我错过了一个明显的解决方案,所以读起来实际上并不那么简单,这确实令人欣慰。 ;)
【解决方案3】:

考虑下面的例子。我相信我已经简化了你的逻辑。

def recursive_prime(n,divisor=2):
    if n == divisor : return True
    elif (n % divisor) == 0: return False
    return recursive_prime(n,divisor+1)

for i in range(2,10):
    print i,'is prime',recursive_prime(i)

【讨论】:

  • 谢谢,但我的目标是真正理解为什么我的版本不工作。
猜你喜欢
  • 2022-01-12
  • 1970-01-01
  • 2016-12-27
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
  • 1970-01-01
相关资源
最近更新 更多