我还没有真正使用方差计算那么多,我不知道会发生什么。实际上我对数学一点都不太好。
我有一个1000000随机数值的数组,范围是0-10000。
数组可能会变得更大,所以我使用64位int作为总和。
我试图找到关于如何计算方差的代码,但我不知道我是否得到了正确的输出。
平均值为4692,中位数为4533.我使用以下代码得到方差1483780.469308:
// size is the element count, in this case 1000000
// value_sum is __int64
double p2 = pow( (double)(value_sum - (value_sum/size)), (double)2.0 );
double variance = sqrt( (double)(p2 / (size-1)) );
我得到了合理的价值吗?
计算有什么问题吗?
答案 0 :(得分:5)
注意:看起来你不是在计算方差。
通过从每个元素中减去平均值并计算这些差异的加权和来计算方差。
所以你需要做的是:
// Get mean
double mean = static_cast<double>(value_sum)/size;
// Calculate variance
double variance = 0;
for(int i = 0;i<size;++i)
{
variance += (MyArray[i]-mean)*(MyArray[i]-mean)/size;
}
// Display
cout<<variance;
请注意,这是样本方差,并且在基础分布未知时使用(因此我们假设均匀分布)。
此外,经过一番挖掘后,我发现这不是一个无偏见的估算器。 Wolfram Alpha对此有一些说法,但作为一个例子,当MATLAB计算方差时,它会返回“偏差校正的样本方差”。
可以通过将每个元素除以size-1
来获得偏差校正的方差,或者:
//Please check that size > 1
variance += (MyArray[i]-mean)*(MyArray[i]-mean)/(size-1);
另请注意,mean
的值保持不变。
答案 1 :(得分:3)
首先,如果您只想了解什么是“合理的”方差,请记住方差基本上是标准偏差的平方。标准差粗略地测量从数据点到其预期值的典型距离。
因此,如果您的数据具有平均值4692,并且您的计算方差为1483780,则表示您的标准偏差约为1218,这表明您的数字往往在3474 - 5910范围附近。所以如果您的数字范围是0 - 10000,那么对我来说这种差异实际上似乎有点低;但它显然取决于您的数据分布。
关于计算本身:您可以使用正在计算的方差来计算方差,因为您第一次使用Welford's Method读取数据(您不必事先知道平均值):< / p>
初始化M1 = x1且S1 = 0.
对于后续的x,请使用重复 公式
Mk = Mk-1 +(xk-Mk-1)/ k Sk = Sk-1 + (xk - Mk-1)*(xk - Mk)。
对于2≤k≤n,第k个估计值 方差是s2 = Sk /(k - 1)。
答案 2 :(得分:3)
只是为了好玩,使用std :: valarray而不是std :: vector和(各种)算法的相同结果略有不同:
template <class T>
T const variance(std::valarray<T> const &v) {
if (v.size() == 0)
return T(0.0);
T average = v.sum() / v.size();
std::valarray<T> diffs = v-average;
diffs *= diffs;
return diffs.sum()/diffs.size();
}
正如雅各布暗示的那样,实际上有两种可能的方差计算版本。就目前而言,这假设您的输入是“宇宙”。如果您只采用整个Universe的示例,则最后一行应使用:(diffs.size()-1)
而不是diffs.size()
。
答案 3 :(得分:2)
可能使用不同的公式?
#include <functional>
#include <algorithm>
#include <iostream>
int main()
{
using namespace std;
vector<double> num( 3 );
num[ 0 ] = 4000.9, num[ 1 ] = 11111.221, num[ 2 ] = -2;
double mean = std::accumulate(num.begin(), num.end(), 0.0) / num.size();
vector<double> diff(num.size());
std::transform(num.begin(), num.end(), diff.begin(),
std::bind2nd(std::minus<double>(), mean));
double variance = std::inner_product(diff.begin(), diff.end(),
diff.begin(), 0.0) / (num.size() - 1);
cout << "mean = " << mean << endl
<< "variance = " << variance << endl;
}
输出: 平均值= 5036.71 variance = 3.16806e + 07
答案 4 :(得分:1)
样本差异计算:
#include <math.h>
#include <vector>
double Variance(std::vector<double>);
int main()
{
std::vector<double> samples;
samples.push_back(2.0);
samples.push_back(3.0);
samples.push_back(4.0);
samples.push_back(5.0);
samples.push_back(6.0);
samples.push_back(7.0);
double variance = Variance(samples);
return 0;
}
double Variance(std::vector<double> samples)
{
int size = samples.size();
double variance = 0;
double t = samples[0];
for (int i = 1; i < size; i++)
{
t += samples[i];
double diff = ((i + 1) * samples[i]) - t;
variance += (diff * diff) / ((i + 1.0) *i);
}
return variance / (size - 1);
}
答案 5 :(得分:0)
由于您正在使用大数字然后对它们执行浮点运算,因此您可能希望在双精度数中执行所有操作;这会为你节省很多演员。
使用pow .. 2
来计算正方形似乎有点尴尬。你可以先计算你的数字,然后将它自己乘以得到一个正方形。
如果你正在进行划分并感觉需要施放,则将操作数(即分子和/或分母)转换为加倍而不是结果。如果划分整数,则会失去准确性。
我不确定你的方差公式是否正确。例如,您可能想查看维基百科中的解释。但我也不是数学专家,所以我不确定你是否有错误。
答案 6 :(得分:0)
由于方差是标准差的平方,因此SO 1174984的答案应该会有所帮助。简短的诊断是你需要计算值的平方和以及值的总和,而你似乎没有这样做。
由于你有10个 6 值,并且任何值的平方可以达到10 8 ,你最终可能得到一个最大为10的平方和SUP> 14 ;你的64位整数最多可以存储10个 18 ,所以你仍然可以处理一万倍的输入,或者数值高达一百万而不是一万,而不会遇到溢出。因此,没有迫切需要转向纯粹的双重计算。