我正在寻找找到数字所有因素的最佳方法。我找到了这段代码,但我听不懂:
import math
def get_factors(n):
return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)
此2 for i in range
完成什么工作?该代码如何计算因子数量?
答案 0 :(得分:4)
生成器表达式一次发现两个因子,因此每次找到一对因子时,都需要在计数中加两个。
这是使用更清晰语法的相同循环:
def get_factors(n):
total_factors = 0
limit = round(math.sqrt(n) + 1)
for i in range(1, limit):
if n % i == 0:
total_factors += 2
return total_factors
这如何用作生成器表达式?让我们解压缩语法。生成器表达式的一般形式为:
result-expression
for
variable
in
iterable-expression
{ {1}} if
这将返回一个生成器,该生成器将是一个包含 predicate
(可以基于 result-expression
的可迭代对象,但是(在这种情况下不是)针对 variable
为真的给定 iterable-expression
中的每个值。
在这种情况下, predicate
是常数result-expression
,因此在 { {1}} 是正确的(也就是说,2
在布尔上下文中是2
,这意味着predicate
会平均划分not n % i
)。>
整个生成器表达式都传递给True
,该表达式采用一个可迭代的参数,并使用i
运算符将其减小为单个值;在这种情况下,它需要使用所有n
并将它们加在一起以总计。
好,为什么有效?那是一个数学问题,而不是编程问题。
slallum在上面的评论中提到了这一点,但是要了解它是如何工作的,请考虑一下一些因素的影响。
让我们选择一个数字,例如12。12有六个因素:1、2、3、4、6、12:
sum
这里有一个明显的对称性:每个因素与另一个因素配对:
+
两个因子系列相互“交叉”的分界线在哪里?这是平方根。 12的平方根大约是3.46,实际上这就是因素分组所围绕的对称线。这是合乎逻辑的,因为平方根意味着什么:作为一个因素,该数仅被计数一次。
优化是,您只需要计算因子的一半(平方根以下的那些),并且知道平方根上方有相应的因子。因此,每次找到一个小于平方根的因数,便要计算两个因数。
正如slallum在评论中指出的那样,这表明此实现是错误的:对于一个完美的平方,它返回的计数将相减一。例如,16有5个因数:1、2、4、8和16,但此实现将说它有6,因为它两次计数4。