我的代码出错:查找素数

时间:2016-12-05 05:55:44

标签: python-3.x

我试图通过在while循环中使用for循环来获取用户输入并通过针对预定义素数元组的循环运行它。如果我们检查的数字使用modulo的余数为零,我们知道它是数字的一个因子。

我要做的是输出一个数字的所有因子,将这些因子附加到数字列表,最后输出素数以及将素数附加到数字列表。

该程序适用于某一点。但是,当我尝试使用82之类的数字时,它表示只有一个因素,实际上,我的目标是让它说因子是2和41,作为一个例子。

我的问题是我在代码中出错以防止这种情况发生?

#Global tuple and list
prime = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31)
numbers = []

# main function
def main():
  # while loop to check on input, and catch value errors
  while True:
    try:
        j = int(input("Enter a positive integer between 1 and 1,000:"))
        j = abs(j)
        break
    except ValueError:
        print("Please enter an integer.")
        main()
    # call factor function, and pass j variable to function            
    l = factors(j)
    #return values from factors function, and print output
    print("The factors of {0} are :".format(j), " ".join(map(str, numbers)))

#def factors function
def factors(j):
    should_restart = True
    #while the loop is running perform calculations
    while should_restart:
    should_restart = False
    for i in prime:
        # if j is evenly divided, continue
        if j % i == 0:
            print("Output: {0}".format(i))
            #if j divided by i equals 1, must be prime
            if j/i == 1:
                numbers.append(i)
                continue
            #set j to j//i and restart the loop    
            else:
                j = j//i
                numbers.append(i)
                should_restart = True
                break
        else:
            continue
# call the main function
main()

1 个答案:

答案 0 :(得分:1)

几个问题:

  • 您声明要在找到新素数时添加到 prime 元组。但是元组是不可变的,所以你最好把它定义为一个列表。另一方面,添加素数没有太多用处,因为你不需要它们用于低于1000的输入:无论 j 在除以所有其他因素之后将是1还是素数。足够了。在列表中添加另一个素数是没有用的。

  • main的递归调用是不必要的,并且一旦您使用无效输入回答,将使输入提示出现太多次。只需离开该呼叫 - while循环将完成所需的操作。

  • 由于数字是函数因子产生的列表,最好让它成为函数的返回值,而不是将其定义为全局变量

  • 变量 should_restart ,以及它上面的循环导致不必要的许多比较:你应该只在循环中坚持使用相同的除数,直到除数不再除以给定的数字。你也应该总是进行分工。有了这样的算法,就不需要再次尝试以前的除数。

  • 条件j/i == 1很奇怪,因为它等同于j == i。虽然这意味着 j 是素数,但它可以与其他情况相结合。相反,只要j > i,就可以通过退出循环来节省一些费用。然后,在循环之后,您仍然具有大于1的 j 值,您可以假设它是一个因素(参见下一点)。

  • 由于 prime 列表中没有所有素数,因此必须保护代码不会产生错误的结果,因为这些数字只包含不在该列表中的素因子。这是通过将最大输入限制设置为1,000来实现的。但是您需要强制执行此限制,并拒绝违反此限制的输入。您还可以通过拒绝大于 prime 列表中最大连续素数(+2)的乘积的输入来使其更通用。

以下是改编的代码:

prime = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31)
# define the maximum value that can be input
max_input = (prime[-1]+2)**2-1
# don't define numbers as global

def main():
    while True:
        try:
            j = int(input("Enter a positive integer between 1 and {}:"
                          .format(max_input)))
            if j >= 1 and j <= max_input: # check the input is in valid range
                break # OK!
        except ValueError:
            print("Please enter an integer.")
            # don't call main recursively here, just let the loop do its job
    numbers = factors(j) # return value is list of factors
    print("The factors of {0} are :".format(j), " ".join(map(str, numbers)))

def factors(j):
    numbers = [] # don't make this a global, but a return value
    for i in prime:
        if i > j: # exit when there is no probability for finding another factor
            break
        # if i is divisor of j, log and remove that factor
        while j % i == 0: # keep repeating
            # i is prime and a divisor, so add it as a factor 
            numbers.append(i)
            # always set j to j//i and try again with the same divisor    
            j = j//i
    if j > 1 and j not in prime: # need to add this non-listed prime as factor
        numbers.append(j)
    return numbers # return the list of factors

main() # call the main function