LINQ是否为聚合SQL函数STDDEV() (标准差)建模?
如果没有,那么计算它的最简单/最佳实践方法是什么?
例:
SELECT test_id, AVERAGE(result) avg, STDDEV(result) std
FROM tests
GROUP BY test_id
Run Code Online (Sandbox Code Playgroud) 我想出来了
n=1;
curAvg = 0;
loop{
curAvg = curAvg + (newNum - curAvg)/n;
n++;
}
Run Code Online (Sandbox Code Playgroud)
我认为这种方式的亮点是:
- 它避免了大数字(如果你总和然后除以可能溢出)
- 你保存一个寄存器(不需要存储总和)
问题可能在于求和误差 - 但我认为通常会有平衡的向上和向下舍入数,因此误差不会大大加总.
你看到这个解决方案有任何陷阱吗?你有更好的建议吗?
我知道这是可以通过提升实现的:
使用boost :: accumulators,如何重置滚动窗口大小,是否保留了额外的历史记录?
但我真的想避免使用提升.我用谷歌搜索,没有找到任何合适或可读的例子.
基本上我想使用最新的1000个数字作为数据样本来跟踪正在进行的浮点数流的移动平均值.
实现这一目标的最简单方法是什么?
我尝试使用圆形阵列,指数移动平均线和更简单的移动平均线,发现圆形阵列的结果最适合我的需要.
使用 32 位浮点值,如果 - 在开始计算时 - 我不知道我将拥有多少个值(在以下示例中,我只是遍历一个向量,那么计算平均值的最佳(数字最准确)方法是什么)我会知道 coult,但让我们假设我最后只知道元素计数)?
我可以做例如
float result = 0.f;
for(float num: numbers) {
result += num;
}
num /= numbers.size();
Run Code Online (Sandbox Code Playgroud)
但随着结果变大,精度也会变大。对于较小的值,在某些时候result += num;实际上不会再改变结果。
我可以
float result = numbers[0]
for(int i=1, i<numbers.size(); i++) {
float frac = (i/float(i+1));
result = result * frac + numbers[i] * (1.0f-frac);
}
Run Code Online (Sandbox Code Playgroud)
但似乎我会应用累积错误来产生这种结果。
有没有更好的方法而不去 64bit double?