【发布时间】:2020-04-09 17:49:48
【问题描述】:
我在Julia 中编写了一个程序来有效地计算数字n 的除数。该算法是原创的(据我所知),大致基于Sieve of Eratosthenes。它基本上是这样工作的:
对于给定的素数
p,让p^k || n;列表中的每个数字m满足p^{k+1} | m被删除,并重复此过程 每个素数p < n。
使用传统的埃拉托色尼筛法在原位计算素数。
function ν(p, n) #returns the smallest power of p that does not divide n
q = 1
for i = 0:n
if mod(n, q) != 0
return (i, q)
end
q *= p
end
end
function divisors(n) #returns a list of divisors of n
dsieve, psieve = BitArray([true for i = 1:n]), BitArray([true for i = 1:n])
psieve[1] = false
for i = 1:n
if psieve[i] && dsieve[i]
#sieving out the non-primes
for j = i^2:i:n
psieve[j] = false
end
#sieving out the non-divisors
v = ν(i, n)[2]
for j = v:v:n
dsieve[j] = false
end
end
end
return dsieve #the code for converting this BitArray to an array of divisors has been omitted for clarity
end
虽然这工作得很好,但我发现同时使用两个筛子效率低下。我认为可以通过允许筛数组中的每个元素取三个不同的值(对应于unchecked、divisor和not divisor)来解决这个问题,但是这样就不能再实现为BitArray .
我也尝试过修改函数ν 以提高效率:
function ν₀(p, n) #the same as ν, but implemented differently
q = p
while mod(n, q) == 0
q = q^2
end
q = floor(Int64, √q)
q < p ? 1 : q * ν₀(p, n÷q) #change 1 to p to get the smallest power of p that does not divide n
end
虽然这更复杂,但它比之前的算法快一点——尤其是当p 除以n 的功率很大时。
注意:我知道有更好的算法可以找到数字的除数。我只是想知道上述算法可以优化到什么程度。如前所述,使用两个筛子相当麻烦,如果能找到一种方法,在不影响效率的情况下消除传统的素数筛子,那就太好了。
【问题讨论】:
标签: algorithm julia integer-division sieve-of-eratosthenes number-theory