[英]Speed Up Finding Number of Elements Between Values Matlab
我創建了一個相當簡單的 MATLAB 腳本來模擬Maths SE 上這個問題中討論的行為。
clearvars;
samples = 1000;
x = 256;
r=exprnd(1/20e6,1,samples); % Generate exponentially distributed randoms.
endTime = sum(r);
quickMean=sum(r(1:x))/x; % Quick calc the mean and median.
quickMedian=0.693 * quickMean;
p = cumsum(r); % Convert event deltas into timestamps
bitstream = false(1,samples);
time = 0;
lastTime = 0;
for i = 1:samples
lastTime = time;
time = time + quickMedian;
if (numel(p(p < time & p > lastTime)) > 0)
bitstream(i) = true;
end
if (time > p(end))
break
end
end
ratio = sum(bitstream)/samples;
該腳本似乎有效,但是,如果我使用大量樣本(比如一百萬),這將是有益的,它真的會爬行。
我假設有問題的陳述是這個:
p(p < time & p > lastTime)
是否有更有效的方法來檢查數組中的任何元素是否介於兩個值之間?
讓我們檢查一下整個表達式:
numel(p(p < time & p > lastTime)) > 0
為了清楚起見,我們可以將其分開:
I = p < time & p > lastTime;
tmp = p(I);
n = numel(tmp);
n > 0
在這里, tmp
的創建非常昂貴:它查看I
的真實位置,並將這些元素復制到一個新數組中。 但是您對這個數組所做的唯一事情就是查看它有多少元素。 邏輯上n
將等於I
中真實元素的數量。 而你並不真正需要這個數字,你只需要知道它是否大於 0。也就是說,你想知道I
為真。 您可以使用any
:
any(p < time & p > lastTime)
正如我在評論中提到的,我們可以利用p
單調遞增的事實並忽略小於lastTime
的值。 如果我們找到p < time
的最后一個值,那么在下一次迭代( lastTime
)中,只有右邊的值可以大於* time
。
clearvars;
samples = 1000;
x = 256;
r=exprnd(1/20e6,1,samples); % Generate exponentially distributed randoms.
endTime = sum(r);
quickMean=sum(r(1:x))/x; % Quick calc the mean and median.
quickMedian=0.693 * quickMean;
p = cumsum(r); % Convert event deltas into timestamps
bitstream = false(1,samples);
time = 0;
lastTime = 0;
% code is the same up to here ---
lastTimeIdx = 1; % index of (last value < lastTime) + 1
for i = 1:samples
lastTime = time;
time = time + quickMedian;
valsInRange = p(lastTimeIdx:end) < time; % p > lastTime & p < time
timeIdx = find(valsInRange, 1, 'last'); % returns [] or index
if ~isempty(timeIdx)
bitstream(i) = true;
lastTimeIdx = lastTimeIdx + timeIdx; % update start of next search
end
if (time > p(end))
break
end
end
ratio = sum(bitstream)/samples;
*其實這是“大於等於”,但是由於p
的值是唯一的,所以它們是一回事。
好的,我剛剛在 Octave 中嘗試histc
。 我很尷尬地說它快得離譜。 快了 4 個數量級。 這是我使用的代碼,但histc
在 MATLAB 中已棄用,並且histcounts
的分箱不同,因此您可能需要稍微嘗試一下。
bitstream_hist = histc(p, [0:samples]*quickMedian) > 0;
bitstream_hist = bitstream_hist(1:samples);
一百萬個樣本在幾分之一秒內完成。 抱歉我沒有早點想到這個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.