MATLAB兰德(,'双倍'),麻烦游泳到平均水平

时间:2014-10-20 15:57:45

标签: matlab random

我发现MATLAB的随机数生成器似乎只能精确到单精度,即使“双倍”'用于返回类型。

我正在使用的简单测试是

  

平均((兰特(1,100000000,'双')))

通过在rand()上执行运行平均而得到的结果相同。平均值以单精度收敛。

我错过了什么吗?

编辑:

快速运行平均值,以总结大量样本:

% use vpa to reduce round off
runningMean = vpa(0);
samples = vpa(0);

% grab groups (significantly faster)
groupSize = 5000000;
while(true)
    runningMean = (runningMean*samples+groupSize*mean(rand(1,1,groupSize)));
    samples = samples + groupSize;
    runningMean = runningMean / samples;

    fprintf('\nN: %d \tmean: %.15f', double(samples), double(runningMean));
end

编辑:

错误与样本的关系图

error vs samples

2 个答案:

答案 0 :(得分:1)

我运行了稍微修改过的代码版本,收集了所有部分结果并绘制了它们。叠加是理论RMS误差:

% use vpa to reduce round off
runningMean = vpa(0);
samples = vpa(0);

% grab groups (significantly faster)
groupSize = 5000000;
K = 1000;
results = NaN(1,K); %// initiallize
for k = 1:K
    runningMean = (runningMean*samples+groupSize*mean(rand(1,1,groupSize)));
    samples = samples + groupSize;
    runningMean = runningMean / samples;
    fprintf('\nIteration: %d \tN: %d \tmean: %.15f',...
        k, double(samples), double(runningMean));
    results(k) = runningMean;
end

%// plot    
loglog((1:k)*groupSize, abs(results-.5))
hold on
loglog(groupSize*[1 k], 1/sqrt(12)./sqrt(groupSize*[1 k]), 'g--') %// theoretical

如您所见,获得的值(蓝色)似乎遵循理论RMS误差(绿色)给出的预期趋势。当然,比较远非完美,因为我将错误的样本值(每个N的单个值)与 RMS进行比较错误。要做得对,你必须运行实验说1e4次;每个N计算那些1e4错误的RMS值;并且 应该与理论RMS值更加一致。尽管如此,即使只有一次运行,这种趋势仍然可以被欣赏。

enter image description here

答案 1 :(得分:1)

同一事物的略微简化的实现:

sz = 5e6;               % batch size
num = 1000;             % number of batches
s = zeros(1,num);       % sum in each batch
for i=1:num
    s(i) = sum(rand(sz,1));
end
csz = sz .* (1:num);    % cumulative sizes
cs = cumsum(s) ./ csz;  % cumulative means

现在我们将结果与@LuisMendo讨论的理论错误一起绘制。我们再次看到理论趋势线后面的经验误差曲线:

subplot(121), semilogx(csz, cs)
line(csz([1 end]), [0.5 0.5], 'Color','m', 'LineStyle',':')
title('x = rand(N,1)'), xlabel('N'), ylabel('mean(x)')
axis tight

subplot(122), loglog(csz, abs(cs-0.5))
line(csz([1 end]), 1./sqrt(csz([1 end])*12), 'Color','m', 'LineStyle',':')
title('x = rand(N,1)'), xlabel('N'), ylabel('|mean(x)-0.5|')
axis tight

screenshot


您还可以尝试使用更好summation algorithm的代码(请参阅FEX上的XSum)。只需将循环中的sum替换为XSum,将最终cumsum替换为:

cs = arrayfun(@(i) XSum(s(1:i)), 1:numel(s)) ./ csz;