문제

난 정말 사용한 분산을 계산하는 많지 확실히 알고 무엇을 기대합니다.실제로 내가 너무 좋지 않으로 수학을 모든.

나는 배열의 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)) );

내가 받고 합리적인 가치입니까?

아무 잘못 계산?

도움이 되었습니까?

해결책

메모: 분산을 계산하는 것처럼 보이지 않습니다.

분산은 모든 요소에서 평균을 빼고 이러한 차이의 가중 합계를 계산하여 계산됩니다.

그래서 당신이해야 할 일은 다음과 같습니다.

// 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 동일하게 유지됩니다.

다른 팁

우선, "합리적인"분산을 처리하려는 경우 분산은 기본적으로 표준 편차 제곱임을 명심하십시오. 표준 편차는 대략 데이터 포인트에서 예상 값까지 일반적인 거리를 측정합니다.

따라서 데이터가 평균 4692가 있고 계산 된 분산이 1483780으로 나오면 표준 편차가 약 1218이므로 숫자가 3474-5910 범위의 근처에있는 경향이 있음을 의미합니다. 숫자의 범위가 0-1000 인 경우 나에게 약간 낮은 것 같습니다. 그러나 그것은 분명히 데이터 분포에 달려 있습니다.

계산 자체에 관해서는 : 처음으로 데이터를 읽을 때 달리기 계산을 사용하여 분산을 계산할 수 있습니다 (미리 평균을 알 필요는 없음) Welford의 방법:

M1 = X1 및 S1 = 0을 초기화하십시오.

후속 X의 경우 재발 공식을 사용하십시오

mk = mk-1 + (xk-mk-1)/k sk = sk-1 + (xk-mk-1)*(xk-mk).

2 ≤ k ≤ n의 경우, 분산의 kth 추정치는 S2 = sk/(k -1)입니다.

재미를 위해 STD :: VECTOR 대신 std :: valarray를 사용하여 동일한 결과와 약간 다른 경로와 (다양한) 알고리즘을 사용합니다.

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

Jacob이 암시 한 바와 같이, 분산 계산의 가능한 두 가지 버전이 있습니다. 그것은 입력이 "우주"라고 가정합니다. 전체 우주의 샘플 만 가져간 경우 마지막 줄은 다음을 사용해야합니다. (diffs.size()-1) 대신에 diffs.size().

어쩌면 다른 공식을 사용합니까?

#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 분산 = 3.16806E+07

샘플 분산 계산 :

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

많은 숫자로 작업 한 다음 플로팅 포인트 작업을 수행하기 때문에 복식으로 모든 것을 할 수 있습니다. 그것은 당신에게 많은 캐스트를 구할 것입니다.

사용 pow .. 2 정사각형을 계산하는 것은 조금 어색한 것 같습니다. 먼저 숫자를 계산 한 다음 자체적으로 곱하여 사각형을 얻을 수 있습니다.

당신이 부서를하고 있고 캐스팅의 필요성을 느끼고 있다면, 캐스팅 피연산자 (즉, 분자 및/또는 분모) 결과보다는 두 배가됩니다. 정수를 나누면 정확도가 상실됩니다.

분산 공식이 정확한지 확실하지 않습니다. 예를 들어 Wikipedia의 설명을보고 싶을 수도 있습니다. 그러나 나는 수학 전문가도 아니기 때문에 실수가 있는지 확실하지 않습니다.

이후 차이가 광장의 표준편차,대한 답변을 그래서 1174984 도와야 한다.짧은 진단에는 당신이 필요로 합을 계산하는 사각형의의 값으로 값의 합계,그리고 당신은하지 않는 것 같습니다.

이후 106 값,그리고 광장의 모든 값을 수 있습까지 108, 할 수 있습으로 제곱 1014;귀하의 64 비트 정수를 저장할 수 있는 최대 1018, 다,그래서 당신은 여전히 열 처리 천 배나 많은 입력 또는 값 이르기까지 최대 백만 대만,실행하지 않고 오버플로우.이 없는 긴급한 필요 따라서,이동하는 순수한 두 번 계산.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top