Python 计算素数和的Lambda函数
在编写一个python程序来计算2到n(包括2到n)之间的素数之和时,我得到了一个错误“生成器不可调用” 谁能帮我解决这个错误,或者建议我在这里遗漏了什么Python 计算素数和的Lambda函数,python,list,lambda,filter,primes,Python,List,Lambda,Filter,Primes,在编写一个python程序来计算2到n(包括2到n)之间的素数之和时,我得到了一个错误“生成器不可调用” 谁能帮我解决这个错误,或者建议我在这里遗漏了什么 n = int(input()) sum = 0 sum = sum(list(filter((lambda n: n%y != 0 for y in range(2, n)), range(2, n+1)))) print(sum) 你的解决方案几乎是正确的。但是您需要在lambda函数中使用all,因为您需要所有n%y!=0声明为真
n = int(input())
sum = 0
sum = sum(list(filter((lambda n: n%y != 0 for y in range(2, n)), range(2, n+1))))
print(sum)
你的解决方案几乎是正确的。但是您需要在lambda函数中使用
all
,因为您需要所有n%y!=0
声明为真:
sum(list(filter((lambda n: all(n%y != 0 for y in range(2,n))), range(2,n+1))))
正如评论中指出的,您可以通过只检查不大于数字平方根的除数来提高代码的效率:
import math
sum(list(filter((lambda n: all(n%y != 0 for y in range(2,int(math.sqrt(n))+1))), range(2,n+1))))
解释
是生成器,而不是布尔值李>n%y!=范围(2,n)中y的0
是对应于all(n%y!=0表示范围(2,n)中的y)
n%2!=0和n%3!=0和。。。和n%(n-1)!=0
n = int(input())
nums = range(2, n + 1)
for i in range(2, n + 1):
nums = list(filter(lambda x: x == i or x % i, nums))
print(sum(nums))
您也可以通过列表理解这样写:
from math import sqrt, floor
sum(( p
for p in range(2, n+1)
if all( p%q != 0 for q in range(2, floor(sqrt(p))+1) ) ))
你不需要检查所有的数字,只需要检查数字的平方根
示例:通过检查10%2==0或10%5==0,可以发现10=2*5不是素数。对于平方根极限,你只需要检查到3,但这很好,因为你已经看到了2,并且定义10为非素数
如果这个应用程序是供您研究的,您可能需要检查以查找素数,这被认为是查找小素数的最有效方法之一
然而,如果你只需要找到素数并求和,你可以使用像..这样的库 1。第一个错误:“TypeError:“generator”对象不可调用”
由于传递给过滤器
内置方法a生成器,您用括号“覆盖”了lambda
方法,因此会出现此错误:
filter((lambda n: n%y != 0 for y in range(2,n)), range(2,n+1))
解决方案:“揭开”括号
filter(lambda n: n%y != 0 for y in range(2,n), range(2,n+1))
2。第二个错误:“SyntaxError:生成器表达式必须为空。”
括号中的“:
lambda n: n%y != 0 for y in range(2,n)
n = int(input())
n_prime_sum = 0
n_prime_sum = sum(list(filter(lambda n: all(n%y != 0 for y in range(2,n)), range(2,n+1))))
n_prime_sum
# n = 10
错误很明显:n%y!=范围(2,n)中y的0是一个生成器,需要用括号括起来,
在这里,您需要测试该数字是否为素数,因此您需要检查生成器中的所有值是否为True
解决方案:使用内置方法all
lambda n: all(n%y != 0 for y in range(2,n))
3。最后一个错误:“TypeError:“int”对象不可调用”
这是因为您正在为变量sum
使用sum
内置方法名,因此sum
不再是内置方法,而是一个整数
解决方案:变量的另一个名称:
n_prime_sum = 0
这是您的代码和修复程序:
lambda n: n%y != 0 for y in range(2,n)
n = int(input())
n_prime_sum = 0
n_prime_sum = sum(list(filter(lambda n: all(n%y != 0 for y in range(2,n)), range(2,n+1))))
n_prime_sum
# n = 10
输出:
17
17
此外,您还可以定义一个生成所有基本btw 2和n(包括)的函数,然后在此函数上应用sum
内置方法:
# original code by David Eppstein, UC Irvine, 28 Feb 2002
# with comments by Eli Bendersky, https://stackoverflow.com/a/568618
def gen_primes(n):
"""Much more efficient prime generation, the Sieve of Eratosthenes"""
D = {}
q = 2 # The running integer that's checked for primeness
while q <= n:
if q not in D:
# q is a new prime.
# Yield it and mark its first multiple that isn't
# already marked in previous iterations
#
yield q
D[q * q] = [q]
else:
# q is composite. D[q] is the list of primes that
# divide it. Since we've reached q, we no longer
# need it in the map, but we'll mark the next
# multiples of its witnesses to prepare for larger
# numbers
for p in D[q]:
D.setdefault(p + q, []).append(p)
del D[q]
q += 1
n = int(input())
n_prime_sum = sum(gen_primes(n))
print(n_prime_sum)
# n = 10
函数gen_prime
的大部分代码来自嗯,在我的想象中,这种方法是最佳的
- 仅用已知素数(而不是每个数)除
- 到给定数字的平方根为止
然后是丑陋化,使之成为lambda
部分
isprime=lambda n:all(n%p!=0 for p in primes)
工作正常,但它忽略了sqrt
magic,然后
isprime=lambda n:all(n%p!=0 for p in (p for p in primes if p<=int(math.sqrt(n))))
我仍然不喜欢将所有素数与S相比较,在中间停止可能更有效,得到一个用<代码>索引(下一个(…))< /代码>的片段可以做到:
isprime=lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))])
只是next()
和index()
遍历列表的一部分两次仍然很难看
然后是外部循环,我将使用functools
中的reduce()
,因为reduce的累加器可能是实际的素数列表,然后它将不是一个单独的变量
第0步将以最简单的方式进行,仍然有变量primes
,但使用元组的可怕技巧,(do,some,things,result)[3]
将执行这些操作,并对结果进行评估:
primes=[2]
isprime=lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))])
maxn=19
ps=functools.reduce(lambda primes,n:(primes.append(n) if isprime(n) else None,primes)[1],range(3,maxn+1),primes)
print(ps)
print(primes)
print(sum(primes)) # ps and primes are the same list actually
然后确定怪物:
import math
import functools
plist=lambda maxn:functools.reduce(lambda primes,n:(primes.append(n) if (lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))]))(n) else None,primes)[1],range(3,maxn+1),[2])
primes=plist(19)
print(primes)
print(sum(primes))
测试:
输出:
附带的信息是:lambdas可能很有用,但实际上您不必总是使用它们。在阅读了所有答案并尝试/测试了自己之后,我重新设计了答案,您可以根据需要进行修改:
# get the user input
n = int(input())
from functools import reduce
# create a list with all the primes within the input number range
n_prime = range(2, n + 1)
for i in range(2, n + 1):
n_prime = list(filter(lambda x: x == i or x % i, n_prime))
# print the list of primes obtained from above
print(n_prime)
# let's add all these numbers in the above list and print the summed value
sum_n_prime = reduce(lambda x, y : x + y, n_prime)
print(sum_n_prime)
传递给过滤器的第一个参数是生成器(lambda n:n%y!=0表示范围(2,n))中的y
,但应该是一个函数,其中一个参数返回True或False。命名错误,sum
是一个内置名称不起作用,因为你在循环的每次迭代中都覆盖nums
。请用输入100
运行代码,你应该得到1060
,这是正确的答案。同意,但用7运行它,你会得到10(假),而不是17(正确)。错过了“包含”部分,修复了它。你可以应用常见的“技巧”对于只运行平方根的内部循环,类似于范围(2,int(math.sqrt(n))+1)中y的。
@tevemadar当然,我只是尊重用户的解决方案并修复了它:)您可以添加改进的解决方案。@WillNess确定。我应该加哪一个?有很多算法,不仅仅是那个些使用暴力的算法……还有sqrt,不是吗?这是一个开始。对于“小”(比如12位数以下)的数字,埃拉托什尼筛是最有效的。试用除法的筛选——没有那么多。您可能应该以某种方式对开头代码中的isprime()
的脆弱性进行评论,也就是说,如果我们在maxn=19
之后插入调用isprime(19)
,它将返回false(或其他一些错误,如未指定的返回值)。@WillNess是的,谢谢,您是对的。起初我是这么想的,但后来我完全忘记了,我只专注于一艘邮轮(这艘邮轮是“安全的”,因为一切都发生在“里面”)。还有,t
[2, 3, 5, 7, 11, 13, 17, 19]
77
# get the user input
n = int(input())
from functools import reduce
# create a list with all the primes within the input number range
n_prime = range(2, n + 1)
for i in range(2, n + 1):
n_prime = list(filter(lambda x: x == i or x % i, n_prime))
# print the list of primes obtained from above
print(n_prime)
# let's add all these numbers in the above list and print the summed value
sum_n_prime = reduce(lambda x, y : x + y, n_prime)
print(sum_n_prime)