【问题标题】:Recursion for my code doesn't seem to work even though I am returning everything即使我返回所有内容,我的代码的递归似乎也不起作用
【发布时间】:2020-02-16 07:49:48
【问题描述】:

我正在编写代码来检查一个数字是否是素数,但我希望参数既是列表又是整数。为此,我正在使用递归,但递归似乎不起作用。

 def prime_checker(suspected_prime):
    if type(suspected_prime) == type(list()):
        result_list = list()
        for x in range(len(suspected_prime)):
            result_list.append(prime_checker(suspected_prime[x]))
        return(result_list)
    else:
        prime_factor, factors, suspected_prime = 2, 0, abs(suspected_prime)
        while factors < 1:
            if suspected_prime % prime_factor == 0:
                factors += 1
            if math.ceil(suspected_prime**0.5) == prime_factor:
                if factors == 0:
                    return True
                else:
                    return False
            prime_factor += 1 

【问题讨论】:

  • 您的代码有问题。在函数中传递一个列表后,它将使用 prime_checker(suspected_prime[x]) 重新运行,然后它将检查 type(suspected_prime) == type(list ()).由于 type(any_list[x] 是整数,它不会重新运行。
  • @ak47hil 你最好把它作为答案而不是评论发布,它太大而且不可读
  • @mangusta 我不确定这是代码的唯一问题,但乍一看似乎就是这样。这就是为什么我将其作为评论回答。我确定它不是完整的回答。
  • @ak47hil 当 if 条件重新运行并且这一次suspended_prime 是一个整数时,那么 else 条件不应该运行吗?我只面临这个问题。递归时,不会进入 else 条件

标签: python function recursion primes


【解决方案1】:

你的list case 和int case 都太复杂了,如果没有损坏的话,让我们看看我们能做些什么。首先,使用isinstance 来测试类型。接下来,你不需要循环遍历索引,你可以更轻松地循环遍历内容。

int 子句而言,您在已知答案后继续进行数学运算——不要在涉及素数时以这种方式浪费时间。此外,如果我们将数字 2 和小于 2 以及偶数视为特殊情况并只专注于测试 奇数 除数,则这种质数测试风格总是更简单:

def prime_checker(suspected_primes):
    if isinstance(suspected_primes, list):
        return [prime_checker(entity) for entity in suspected_primes]

    suspected_prime = abs(suspected_primes)

    if suspected_prime < 2:
        return False

    if suspected_prime % 2 == 0:
        return suspected_prime == 2

    for divisor in range(3, int(suspected_prime**0.5) + 1, 2):
        if suspected_prime % divisor == 0:
            return False

    return True

print(prime_checker([1, [2, 3], 4, [5, 6, [7, 8], 9]]))
print(prime_checker(13))

输出

> python3 test.py
[False, [True, True], False, [True, False, [True, False], False]]
True
>

【讨论】:

  • 我看到了问题。谢谢!
【解决方案2】:

目前你有:

def prime-checker (input could be scalar or a list)

策略 1:(删除素数检查器内的循环,始终处理标量,即非列表)。所以你有:

def prime_checker (scalar, ie. non-list input arg) :

要处理此问题,请将您的实现更改为始终处理标量。在素数检查器功能之外进行外部循环。有了这个,您的素数检查器将只有数学计算部分,所以它会更简单,更容易理解。

策略 2: 或者,如果您坚持让列表在 prime-checker 中循环。

案例 1:如果您的输入只是一个数字,例如 45。然后将输入 arg 发送为 [45] 因此,prime-checker 的外部调用(来自外部调用者)将变为

results = prime_checker( [45])

案例 2:如果您的输入是一个列表,比如 list1,那么您的调用是

results = prime_checker (list1).

所以,现在您的实现总是期望并处理一个列表。

# we always get input as a list (hence I changed the arg name)
 def prime_checker(suspected_list):
    # this branch *looks* recursive, but actually only handles a list
    if (len(suspected_list) > 1) :
        result_list = []
        for prime_candidate in suspected_list:
            result_list.append(prime_checker([prime_candidate]) # recur, as a list
        return(result_list)
    else: (when suspected list has only 1 entry)
        # this branch does the actual prime calculation for a single input
        suspected_prime = suspected_list[0]
        prime_factor, factors, suspected_prime = 2, 0, abs(suspected_prime)
        while factors < 1:
            if suspected_prime % prime_factor == 0:
                factors += 1
            if math.ceil(suspected_prime**0.5) == prime_factor:
                if factors == 0:
                    return True
                else:
                    return False
            prime_factor += 1 

【讨论】:

  • 你认真计算不变 math.ceil(suspected_prime**0.5)在一个循环中一遍又一遍?如果你做factors += 1 你知道答案是False,为什么要把它画出来? (为什么要使用 factors?)您扭曲的实现掩盖了您区分长度为 1 的列表和更长的列表作为处理列表与标量的替代方法的有趣点。
  • 我不是要纠正或优化 Prime 计算。 OP 遇到递归调用问题。我只是给出了以不同方式组织代码的建议。我不是要完成代码.. 要点是:在递归调用中,您希望将输入 args 保持为一致的数据类型。另外,递归调用总是有一个基本(零)案例 - 在 OP 的实现中,基本案例是输入 数据类型更改 从列表到标量。我用长度为 1 的列表替换了那个基本情况。
【解决方案3】:

我认为这应该适用于您的代码:

def prime(suspected_prime):
if type(suspected_prime) == list:
    result_list = list()
    for x in suspected_prime:
        result_list.append(prime(x))
    return(result_list)
else:
    factors,suspected_prime = 0,abs(suspected_prime)
    root = int(suspected_prime**0.5)
    for x in range (2,(root+1)):
        if(factors == 1):
            break
        elif(suspected_prime%x == 0):
            factors = 1  
            return False

    if (factors == 0):
        return True

您可以根据需要更改 if-else 语句。

【讨论】:

  • return 语句之后有两条语句永远不会被执行。你可以扔掉factors 变量和与之相关的所有逻辑——最终的测试只是变成了return True
  • 我已经更正了代码以包含您的更正。Break 语句仍应运行,因为它会中断循环流程并且与返回无关。
  • 没有像我建议的那样丢弃factors,你让代码变得更复杂,而不是更好。
  • 是的,我会删除因素
  • 你是对的..但是更好地实现你的问题是为一个数字创建一个素数检查器,然后使用 map 函数遍历一个列表。代码会更多干净,结果是一样的
猜你喜欢
  • 1970-01-01
  • 2020-08-17
  • 2014-03-14
  • 2021-12-20
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2017-12-22
相关资源
最近更新 更多