正在对一个正在运行的进程进行基准测试,其中“累计”计算以下数字(从以前的值+新元素开始):
持续时间的 Standard Deviation(σ)也应该计算出来,因为它表示statistical dispersion。
基于应用程序,存储每个元素/数字很不方便,因此有必要针对先前的值和新元素进行计算。
示例:
NewElement Min Max Avg StdDev // AllElements (which are NOT meant to be stored)
1 1 1 1 - [1]
2 1 2 1.5 0.5 [1,2]
3 1 3 2 0.8164965809277 [1,2,3]
4 1 4 2.5 1.1180339887499 [1,2,3,4]
0 0 4 2 1.4142135623731 [1,2,3,4,0]
(this是SD的在线计算器,用于参考值)
目标的简化版本是:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
// newStats.sd = ??? that's the problem
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
// initial SD is theoretically controversial (N/A), but that's not the point
sd: 0,
};
// loopStart goes here ... an infinite one
// many things goes here ... eventually, we have a `newElement`
stats = calculateNewStats(stats, newElement);
// loopEnd goes here
进行了一段时间的搜索,找到并仔细应用了一些数学方程式(如this),但结果数字不正确。
答案 0 :(得分:2)
the page you linked上的算法确实有效,这是一个有效的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.avg * stats.count + newElement) / newStats.count;
newStats.sd = Math.sqrt(
(
(newStats.count - 1) * stats.sd * stats.sd +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count)
);
return newStats;
};
// initial values
let stats = {
count: 0,
min: 0,
max: 0,
avg: 0,
sd: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}
也许您错过了最后一句话?
如果要总体方差或标准差,请用N替换N-1,用N-1替换N-2。
注意:添加元素时,精度会有所降低,精度会有所提高。我建议:
stats
一起存储在sd
中;现在,我正在计算方差的平方根以获取SD,然后对SD进行平方以在下一次迭代中获取方差stats
中,而不是每次迭代都用stats.avg * stats.count
重新计算您将在stats
中再存储2个数字,但是您的数字应该会更精确。
这是一个更好的实现:
const calculateNewStats = (stats, newElement) => {
const newStats = {};
newStats.count = stats.count + 1;
newStats.total = stats.total + newElement;
newStats.min = Math.min(stats.min, newElement);
newStats.max = Math.max(stats.max, newElement);
newStats.avg = (stats.total + newElement) / newStats.count;
newStats.variance = (
(newStats.count - 1) * stats.variance +
(newElement - newStats.avg) * (newElement - stats.avg)
) / (newStats.count);
newStats.sd = Math.sqrt(newStats.variance);
return newStats;
};
// initial values
let stats = {
count: 0,
total: 0,
min: 0,
max: 0,
avg: 0,
sd: 0,
variance: 0
};
let newElements = [1, 2, 3, 4, 0];
for (let newElement of newElements) {
stats = calculateNewStats(stats, newElement);
console.log(stats);
}