此代码需要很长时间才能运行(超过10分钟)。有什么方法可以优化它,以便在不到一分钟的时间内完成?
clear all;
for i = 1:1000000
harmonicsum = 0;
lhs = 0;
for j = 1:i
% compute harmonic sum
harmonicsum = harmonicsum + 1/j;
% find sum of factors
if (mod(i,j)==0)
lhs = lhs + j;
end
end
%define right hand side (rhs) of Riemann Hypothesis
rhs = harmonicsum + log(harmonicsum) * exp(harmonicsum);
if lhs > rhs
disp('Hypothesis violated')
end
end
答案 0 :(得分:6)
@b3 has a great vectorization of rhs
.
但有一个错字,需要使用times
而不是mtimes
:
harmonicsum = cumsum(1 ./ (1:1e6));
rhs = harmonicsum + log(harmonicsum) .* exp(harmonicsum);
对于lhs
,我基于Eratosthenes的Sieve松散地提出以下建议:
lhs = 1 + [1:1e6];
lhs(1) = 1;
for iii = 2:numel(lhs)/2
lhs(2*iii:iii:end) = lhs(2*iii:iii:end) + iii;
end;
执行时间仅为2.45秒(针对此问题的一半)。包括rhs
和find
计算在内的总计不到3秒。
我目前正在运行其他版本以确保结果相同。
编辑:发现了lhs(1)
的一个错误并且特殊情况(这是一个特例,唯一的自然数,其中1和N不是不同的因素)
答案 1 :(得分:4)
将算法矢量化,我可以将执行时间略微缩短到约8.5分钟。在一个陈述中计算所有的谐波总和:
harmonicsum = cumsum(1 ./ (1:1e6));
您现在可以在一个声明中计算右侧:
rhs = harmonicsum + log(harmonicsum) .* exp(harmonicsum);
我无法对因子的确定进行矢量化,因此这是我能想出的最快的方法。 MATLAB的FACTOR命令允许您为每次迭代生成所有素因子。然后,我们使用UNIQUE和NCHOOSEK计算所有可能组合的唯一产品集。这避免了将每个整数作为一个因子进行测试。
lhs = zeros(1e6, 1); for ii = 1:1e6 primeFactor = factor(ii); numFactor = length(primeFactor); allFactor = []; for jj = 1:numFactor-1 allFactor = [allFactor; unique(prod(nchoosek(primeFactor, jj), 2))]; end lhs(ii) = sum(allFactor) + 1 + ii; end lhs(1) = 1;
找出违反黎曼假设的指数:
isViolated = find(lhs > rhs);
答案 2 :(得分:0)
内循环执行大约1000000 *(1000000 + 1)/ 2 = 500000500000次!难怪它很慢。也许你应该尝试不同的近似方法。