我正在编写一个Matlab程序以通过级数求和来计算pi
A = Sum of a_i from i=1 to N
其中
pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 ...
要通过级数求和来计算pi,建议的方法是设置
a_i = (-1)^(i+1)/(2i-1)
为此,我在下面编写了程序
n=100;
f=[];
for jj=1:n
ii=1:jj;
f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1) )];
end;
hold on
plot(f)
title('Computing of \pi using a finite sum')
xlabel('Number of summations')
ylabel('Estimated value of \pi')
plot(1:size(f,2),ones(size(f))*pi)
此程序显示,在N=80
附近,级数逼近有些准确。
我现在正尝试调整程序,以使y-axis displays total calculation time T_N
和x-axis displays N (the number of summations)
。随着N的增加,总的计算时间T_N应该增加。理想情况下,我希望图形显示的内容接近T(N)
和N
为此,我对原始程序进行了如下调整
n=100;
f=[];
tic
for jj=1:n
ii=1:jj;
f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1) )];
end;
hold on
plot(f)
title('Time it takes to sum \pi using N summations')
xlabel('Number of summations (N)')
ylabel('Total Time (T_N)')
plot(1:size(f,2),toc)
slope = polyfit(1:size(f,2),toc,1);
这看起来是错误的。我一定不正确地应用了Matlab中的内置计时功能(tic和toc)。因此,我将分析我的代码并提出两个问题-
如何调整上面的代码,以便y轴正确显示每个总和N的总计算时间?看来我在plot(1:size(f,2),toc)
中做错了。
获得y-axis
以显示正确的total calculation time (T_N)
之后,我应该能够使用polyfit
命令来找到T(N)/N
的斜率。这会给我T(N) and N
之间的线性关系。然后,我可以使用slope = polyfit(1:size(f,2),toc,1)
的值进行计算
t_N = a + b*N
其中t_N
是为N
的每个值计算的,而b
是通过polyfit命令计算的斜率。
我认为正确显示values of a and b
并正确引用polyfit命令后,应该能够找到y-axis
。
答案 0 :(得分:3)
您的代码中有几处可以改进的地方:
f
应该预先分配,以免浪费时间重复分配内存。tic
应该在循环内调用,以重新启动秒表计时器。toc
时,您将从上一个tic
开始获取 current 时间。花费的时间应该存储在向量中(也要预先分配)。timeit
(请参见下文)。包含这些更改的代码是:
n = 100;
f = NaN(1,n); % preallocate
times = NaN(1,n); % preallocate
repeat_factor = 1e4; % repeat computations for better time accuracy
for jj=1:n
tic % initiallize time count
for repeat = 1:repeat_factor % repeat many times for better time accuracy
ii=1:jj;
f(jj) = 4*sum( ((-1).^(ii+1))./(2.*ii-1) ); % store value
end
times(jj) = toc; % store time
end
times = times / repeat_factor; % divide by repeat factor
plot(f)
title('Time it takes to sum \pi using N summations')
xlabel('Number of summations (N)')
ylabel('Total Time (T_N)')
figure % new figure for time
plot(1:size(f,2), times)
p = polyfit(1:size(f,2),times,1);
slope = p(1);
使用timeit
来测量时间可能会提高精度(但不是很好,因为如上所述,您要计时的计算速度非常快)。要使用timeit
,您需要使用要计时的代码定义一个函数。最简单的方法是使用没有输入参数的anonymous function。参见下面的代码。
n = 100;
f = NaN(1,n); % preallocate
times = NaN(1,n); % preallocate
for jj=1:n
ii=1:jj;
fun = @() 4*sum( ((-1).^(ii+1))./(2.*ii-1) );
f(jj) = fun(); % store value
times(jj) = timeit(fun); % measure and store time
end
plot(f)
title('Time it takes to sum \pi using N summations')
xlabel('Number of summations (N)')
ylabel('Total Time (T_N)')
figure % new figure for time
plot(1:size(f,2), times)
p = polyfit(1:size(f,2),times,1);
slope = p(1);
答案 1 :(得分:2)
如果我正确理解了您的问题,我认为这里有两个不同的问题。首先,绘制结果函数,然后绘制经过时间,该时间比pi小几个数量级:
hold on
plot(f) % <---- Comment me out!
...stuff...
plot(1:size(f,2),toc)
第二,您需要存储循环每次通过的执行时间:
n=100;
f=[];
telapsed = zeros(1,n);
tic
for jj=1:n
ii=1:jj;
f=[f 4*sum( ((-1).^(ii+1))./(2.*ii-1) )];
telapsed(jj) = toc;
end
hold on
% plot(f)
title('Time it takes to sum \pi using N summations')
xlabel('Number of summations (N)')
ylabel('Total Time (T_N)')
plot(1:n,telapsed)
slope = polyfit(1:n,telapsed,1);
请注意新的polyfit表达式的执行时间斜率。有帮助吗?