上一篇写了Rust版本的产生水仙花数的尝试,如果用Julia来写一下,会有什么不同?
function get_nums(n::Int64)
str =string(n);
len =length(str)
nums =Int64[]
for i =1:len
push!(nums,parse(Int64,str[i]))
end
return nums,len;
end
function is_fit_num(n::Int64)
nums,len =get_nums(n);
return sum(nums.^len)==n
end
list =100:1:9000000;
@time data =[x for x in list if is_fit_num(x)]
output: 13个水仙花数的运行情况
2.985466 seconds (63.00 M allocations: 4.008 GiB, 17.54% gc time)
list =100:1:50000000;
output: 17个水仙花数的运行情况
17.599224 seconds (350.00 M allocations: 22.337 GiB, 16.64% gc time)
和Rust的比较:可见Rust是优势较大。
尝试一:改成下面的方式,效率也差不多:
list =100:1:50000000;
function get_result(list)
vec =Int64[]
for i in list
if is_fit_num(i)
push!(vec,i);
end
end
return vec
end
@time get_result(list)
尝试二:启用digits函数
Julia内置了一个digits函数,如,可以把5016,拆成5,0,1,6四个数字。这样,我们就不用手写一个了。
1、更简洁方式
如果是追求代码短小,你完全可以一行搞定:
@time data =[x for x in list if sum(digits(x).^length(digits(x)))==x]
代价是,速度并没有提升,还是在原来17秒的水平上(17位水仙花数)。
2、更快的方式
重要的是:
因此,优化后的程序:(digits/@inline两个方面)
function get_nums(n::Int64) # 在函数前面可以加@inline
nums =digits(n)
return nums,length(nums);
end
function is_fit_num(n::Int64) # 在函数前面可以加@inline
nums,len =get_nums(n);
return sum(nums.^len)==n
end
list =100:1:50000000;
@time data =[x for x in list if is_fit_num(x)]
这样,可以从原来17秒的基础上,优化到11秒左右。