2015-10-21 439 views
3

,所以我已经张贴了几次,以前我的问题是相当含糊计算标准差和变异在C++

我开始C++本周一直在做一个小项目

所以我想到calc下标准差&方差

我的代码加载100个整数的文件,并把它们放到一个数组,统计他们,Calcs(计算)的意思,总之,VAR和SD

但我在与方差有点麻烦

我不断收到一个巨大的数字 - 我有一种感觉,它与它的计算

我均值和金额做都行

任何帮助或建议吗?

NB:

sd & mean calcs

干杯,

杰克

using namespace std; 
    int main() 

{ 

int n = 0; 
int Array[100]; 
float mean; 
float var; 
float sd; 
string line; 
float numPoints; 

ifstream myfile(“numbers.txt"); 

if (myfile.is_open()) 

{ 
    while (!myfile.eof()) 

    { 
     getline(myfile, line); 

     stringstream convert(line); 

     if (!(convert >> Array[n])) 

     { 
      Array[n] = 0; 
     } 
     cout << Array[n] << endl; 

     n++; 

    } 

    myfile.close(); 

    numPoints = n; 

} 
else cout<< "Error loading file" <<endl; 

int sum = accumulate(begin(Array), end(Array), 0, plus<int>()); 

cout << "The sum of all integers: " << sum << endl; 

mean = sum/numPoints; 

cout << "The mean of all integers: " << mean <<endl; 

var = ((Array[n] - mean) * (Array[n] - mean))/numPoints; 

sd = sqrt(var); 

cout << "The standard deviation is: " << sd <<endl; 

return 0; 

} 
+0

在'(数组[n] - 平均值)'是不'N'比元件的数量多一个已阅读?此外,['while(!myfile.eof())']几乎总是错的](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) –

+0

你应该使用double而不是float – FredK

+0

''''应该是''' –

回答

7

至于其他的答案被马蹄正确的建议,你将不得不使用一个循环,否则计算方差声明

VAR =((数组[n] - mean)*(Array [n] - mean))/ numPoints;

将只考虑阵列中的单个元素。

只是提高马蹄的推荐代码:

var = 0; 
for(n = 0; n < numPoints; n++) 
{ 
    var += (Array[n] - mean) * (Array[n] - mean); 
} 
var /= numPoints; 
sd = sqrt(var); 

你和工作正常,即使没有,因为你正在使用积累已经具有里面循环功能使用循环,但并不明显的代码,看看accumulate的等价行为,以清楚了解它在做什么。

注:X ?= Y是短期的X = X ? Y其中?可以是任何操作数。 你也可以使用pow(Array[n] - mean, 2)来取代正方形,而不是将它自己放大,使它更整齐。

+1

感谢'Note'它是有用的。将你的代码与马蹄相比为什么for语句比while更好?还是没有真正的区别? – Jack

+2

@jack技术上在**和**循环(语法除外)之间没有区别,但通常在需要时:(1)在启动循环前初始化一个变量,(2)在变量循环结束,然后(3)想要检查一个条件来重复;然后** for **使代码更具可读性,并且确保您不会忘记这三者中的任何一个。 –

1

你方差计算是外循环,因此它只是基于n== 100 value.你需要一个额外的环。

您需要:

var = 0; 
n=0; 
while (n<numPoints){ 
    var = var + ((Array[n] - mean) * (Array[n] - mean)); 
    n++; 
} 
var /= numPoints; 
sd = sqrt(var); 
+0

我认为你在最后一行有一个错字 – Jason

+1

@ Jason:是的,真的,但Ahmeds的解决方案现在很好地解决了这个问题 – horseshoe

+1

这仍然是好事修复你的拼写错误 – Jason

1

两种简单的计算标准偏差的方法& C++中的差异。

#include <math.h> 
#include <vector> 

double StandardDeviation(std::vector<double>); 
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 std = StandardDeviation(samples); 
    return 0; 
} 

double StandardDeviation(std::vector<double> samples) 
{ 
    return sqrt(Variance(samples)); 
} 

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); 
} 
0

不是写出更多的循环,你可以创建一个function object传递给std::accumulate计算平均值。

template <typename T> 
struct normalize { 
    T operator()(T initial, T value) { 
     return initial + pow(value - mean, 2); 
    } 
    T mean; 
} 

虽然我们是在它,我们可以使用std::istream_iterator做文件加载,std::vector因为我们不知道有多少价值有在编译时。这给了我们:

int main() 
{ 
    std::vector<int> values(100); // initial capacity, no contents yet 

    ifstream myfile(“numbers.txt"); 
    if (myfile.is_open()) 
    { 
     std::copy(std::istream_iterator<int>(myfile), std::istream_iterator<int>(), std::back_inserter(values)); 
     myfile.close(); 
    } 
    else { cout<< "Error loading file" <<endl; } 

    float sum = std::accumulate(values.begin(), values.end(), 0, plus<int>()); // plus is the default for accumulate, can be omitted 
    std::cout << "The sum of all integers: " << sum << std::endl; 
    float mean = sum/values.size(); 
    std::cout << "The mean of all integers: " << mean << std::endl; 
    float var = std::accumulate(values.begin(), values.end(), 0, normalize<float>{ mean }); 
    float sd = sqrt(var); 
    std::cout << "The standard deviation is: " << sd << std::endl; 
    return 0; 
} 
0

下面是使用std::accumulate另一种方法,但没有使用pow。另外,我们可以使用匿名函数来定义在计算均值后如何计算方差。请注意,这会计算无偏样本方差。

#include <vector> 
#include <algorithm> 
#include <numeric> 

template<typename T> 
T variance(const std::vector<T> &vec) 
{ 
    size_t sz = vec.size(); 
    if (sz == 1) 
     return 0.0; 

    // Calculate the mean 
    T mean = std::accumulate(vec.begin(), vec.end(), 0.0)/sz; 

    // Now calculate the variance 
    auto variance_func = [&mean, &sz](T accumulator, const T& val) 
    { 
     return accumulator + ((val - mean)*(val - mean)/(sz - 1)); 
    }; 

    return std::accumulate(vec.begin(), vec.end(), 0.0, variance_func); 
} 

的如何使用此功能的示例:

int main() 
{ 
    std::vector<double> vec = {1.0, 5.0, 6.0, 3.0, 4.5}; 
    std::cout << variance(vec) << std::endl; 
}