2015-10-21 635 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; 
}