Daniel Lichtblau pointed out以两种方式得出素因子数(PrimeOmega
)与不同素因子数({{1}之间的差异的时间差异让我感到惊讶一个整数,n。所以我决定再深入研究一下。
以下函数PrimeNu
和g1
是使用ones丹尼尔以及其他三个的略微变化。它们都返回从1到n的无平方整数的数量。但差异相当大。任何人都可以解释差异背后的原因。特别是,为什么g2
Sum
提供了这样的速度优势?
g5
比较:
g1[n_] := Count[PrimeOmega[Range[n]] - PrimeNu[Range[n]], 0]
g2[n_] := Count[With[{fax = FactorInteger[#]},
Total[fax[[All, 2]]] - Length[fax]] & /@ Range[n], 0]
g3[n_] := Count[SquareFreeQ/@ Range[n], True]
(* g3[n_] := Count[SquareFreeQ[#] & /@ Range[n], True] Mr.Wizard's suggestion
incorporated above. Better written but no significant increase in speed. *)
g4[n_] := n - Count[MoebiusMu[Range[n]], 0]
g5[n_] := Sum[MoebiusMu[d]*Floor[(n - 1)/d^2], {d, 1, Sqrt[n - 1]}]
结果:
n = 2^20;
Timing[g1[n]]
Timing[g2[n]]
Timing[g3[n]]
Timing[g4[n]]
Timing[g5[n]]
修改
Mysticial提出了后一种惯例正在获得订单收益的可能性 - 一些缓存可能一直在进行。
所以让我们按相反的顺序运行比较:
{44.5867, 637461}
{11.4228, 637461}
{4.43416, 637461}
{1.00392, 637461}
{0.004478, 637461}
反向比较的结果:
n = 2^20;
Timing[g5[n]]
Timing[g4[n]]
Timing[g3[n]]
Timing[g2[n]]
Timing[g1[n]]
结论:合理的猜测,但数据不支持。
答案 0 :(得分:8)
ModebiusMu对于小数字有一些专用的快速筛分代码,实际上是快捷方式实际分解,只是在找到因子时计算。它不会添加像PrimeOmega这样的指数,因此它确实没有任务。每当它检测到具有多重性的素因子时,它也会短路。
我认为截止时间恰好在2 ^ 20左右。没有时间进行测试,但确实可能会慢一些。
g4的答案。显然g5正在使用程序员的聪明才智(当然没有错),因此速度提升。
至于g3,它实质上是在实现代码方面对g4的调用。在这种情况下,瓶颈是预处理开销,因为它是用mathematica而不是C代码实现的。我怀疑如果使用更大的输入,这将不太明显,因为在这种情况下,花费更多的时间来完成实际工作而不是Mathematica解释器开销。我再次测试过这个。