我对Julia印象非常深刻,因为它在处理器密集的Euler Project问题上跑得比D快。 #303如果有人有兴趣。
奇怪的是,朱莉娅的BigInts似乎有多缓慢。奇怪,因为我看了他们的表现相当不错。
以下是使用Euler递推公式计算15k分区数的Julia程序。
function eu78()
lim = 15000
ps = zeros(BigInt, lim)
function p(n) #applies Euler recurrence formula
if n < 0
return BigInt(0)
elseif n == 0
return BigInt(1)
elseif ps[n] > 0
return ps[n]
end
s = BigInt(0)
f = BigInt(-1)
for k = 1 : n
f *= -1
t1 = (k * (3k - 1)) ÷ BigInt(2)
t2 = (k * (3k + 1)) ÷ 2
s += f * (p(n - t1) + p(n - t2))
end
ps[n] = s
end
for i = 1 : lim
p(i)
end
println(ps[lim])
end
eu78()
以惊人的3分43秒跑步,以产生132位数的答案。
使用pypy运行的等效Python代码只需要8秒钟。
我做错了什么?
答案 0 :(得分:7)
Int
值是机器整数,因此BigInts的性能并不重要。 BigInt性能的真正提升将来自于将Julia的BigInt类型与GC集成,并允许小的BigInt值被分配堆栈 - 并且存在于寄存器中。但是,我们还没到那里。
答案 1 :(得分:3)
以下版本在我的机器上使用Julia 0.4:
在12秒内运行const lim = 6*10^4
const ps = zeros(Int64, lim)
ps[1] = 1
function p(n) #applies Euler recurrence formula for the number of partitions
n < 0 && return 0
n == 0 && return 1
ps[n] > 0 && return ps[n]
s, f = 0, -1
for k = 1:n
f *= -1
t1 = (k * (3k - 1)) ÷ 2
t2 = (k * (3k + 1)) ÷ 2
s += f * (p(n - t1) + p(n - t2))
end
siz = 10^9
ps[n] = mod(s, siz)
end
function eu78(lim=6*10^4)
for i = 10:lim
a = p(i)
if mod(a, 1000000) == 0
return (i, a)
end
end
end
@time eu78(10) # warm-up
@time eu78(6*10^4)
答案 2 :(得分:0)
感谢Stefan的快速反应。
我觉得自从朱莉娅版本没有bigint仍然比pypy慢几个数量级时还有其他事情发生。
所以这不是一个答案,而是一个不同的问题。
欧拉项目的问题是找到第一个数字,其数量总计为百万分之一。所以我们需要超过6位有效数字,因此可以使用机器整数来完成。
以下是Julia中的这个版本,它在2分44秒内完成。
function eu78()
const lim = 6 * 10 ^ 4
ps = zeros(Int64, lim)
ps[1] = 1
const siz = 10 ^ 9
function p(n) #applies Euler recurrence formula for the number of partitions
if n < 0
return 0
elseif n == 0
return 1
elseif ps[n] > 0
return ps[n]
end
s, f = 0, -1
for k = 1 : n
f *= -1
t1 = (k * (3k - 1)) ÷ 2
t2 = (k * (3k + 1)) ÷ 2
s += f * (p(n - t1) + p(n - t2))
end
ps[n] = mod(s, siz)
end
for i = 10 : lim
a = p(i)
if mod(a, 1000000) == 0
println(i,'\n', a)
break
end
end
end
eu78()
(顺便说一下,谢谢你们在Julia中使用%来给出余数而不是更常用的模数。:)这花了我整整一个晚上试图让它返回答案,任何%$#%&amp;!而不是一无所获。)
在pypy中运行的python版本在41秒内完成,四分之一的时间。 (公平地说,在python2中运行,需要13分48秒。)
那么问题是什么?第20行的双递归?我怎样才能加快速度?并不是说读这篇文章的人都会关心,但Project Euler中有一分钟的程序执行规则。