سؤال

أنا لم تستخدم الفرق حساب كثيرا, و أنا لا أعرف تماما ما يمكن توقعه.في الواقع أنا لست جيدة جدا مع الرياضيات على الإطلاق.

لدي مجموعة من 1000000 عشوائية القيم الرقمية في مجموعة 0-10000.

مجموعة يمكن أن تنمو أكبر ، لذلك أنا استخدم 64 بت الباحث عن المبلغ.

لقد حاولت أن تجد رمز على كيف احسب الفرق, ولكن أنا لا أعرف ما إذا كنت الحصول على إخراج الصحيح.

يعني هو 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;

لاحظ أن هذا هو الفرق العينة ، ويستخدم عندما يكون التوزيع غير معروف (إذا افترضنا توزيع موحد).

أيضا, بعد بعض البحث وجدت أن هذا ليس هو غير مقدر. ولفرام ألفا لديه ما يقوله حول هذا الموضوع ، ولكن على سبيل المثال ، عندما MATLAB يحسب الفرق ، فإنه يعود على "التحيز-تصحيح عينة من الفرق".

التحيز-تصحيح الفرق يمكن الحصول عليها عن طريق قسمة كل عنصر من قبل size-1, أو:

//Please check that size > 1
variance += (MyArray[i]-mean)*(MyArray[i]-mean)/(size-1); 

أيضا نلاحظ أن قيمة mean لا يزال هو نفسه.

نصائح أخرى

أولا, إذا كنت تبحث فقط للحصول على التعامل مع ما هو "معقول" الفرق, نضع في اعتبارنا أن الفرق هو في الأساس الانحراف المعياري المربعة.الانحراف المعياري تقريبا التدابير نموذجية المسافة من نقطة بيانات إلى القيمة المتوقعة.

حتى إذا كانت البيانات الخاصة بك قد يعني 4692 و يحسب الفرق هو الخروج إلى 1483780 ، وهذا يعني أن الانحراف المعياري هو عن 1218 ، التي من شأنها أن تشير إلى الأرقام الخاصة بك تميل إلى أن تكون في مكان ما بالقرب من مجموعة 3474 - 5910.حتى أن الفرق يبدو في الواقع منخفضة قليلا لي إن مجموعة من الأرقام الخاصة بك هو 0 - 10000;ولكن من الواضح أنه يعتمد على توزيع البيانات الخاصة بك.

أما بالنسبة حساب نفسها:يمكنك حساب التباين باستخدام تشغيل الحساب كما كنت تقرأ البيانات الخاصة بك في المرة الأولى (لا يجب أن أعرف مقدما) باستخدام ويلفورد طريقة:

تهيئة 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::valarray بدلا من std::المتجهات و (مختلف) الخوارزميات:

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

كما يعقوب ألمح حقا أن هناك اثنين من الإصدارات الممكنة من الفرق حساب.كما يقف هذا يفترض المدخلات الخاصة بك هي "الكون".إذا كنت قد اتخذت عينة فقط من مجمل الكون ، السطر الأخير يجب استخدام: (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.16806 e+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 لحساب مربع يبدو محرجا بعض الشيء.يمكنك حساب عدد أول ، ثم اضربها نفسها للحصول على شكل مربع.

إذا كنت تفعل شعبة تشعر بالحاجة إلى الزهر ، يلقي المعاملات (أيالبسط أو المقام) إلى مضاعفة بدلا من النتيجة.أنت تفقد دقة إذا قمت بتقسيم الأعداد الصحيحة.

لست متأكدا إذا كان لديك صيغة الفرق هو الصحيح.قد ترغب في النظر في التفسير في ويكيبيديا ، على سبيل المثال.ولكن أنا لا خبير الرياضيات سواء ، لذلك أنا لست متأكدا من أن لديك خطأ.

منذ التباين هو مربع الانحراف المعياري, إجابات حتى 1174984 ينبغي أن تساعد.قصيرة التشخيص هو أن تحتاج إلى حساب مجموع مربعات القيم وكذلك مجموع القيم و لا يبدو أن تفعل ذلك.

منذ لديك 106 والقيم مربع من أي قيمة يمكن أن تصل إلى 108, هل يمكن في نهاية المطاف مع مجموع المربعات تصل إلى 1014;الخاص بك 64 بت الصحيحه يمكن تخزين ما يصل إلى 1018, لذا كنت تستطيع التعامل مع عشرة آلاف أضعاف عدد المدخلات أو قيم تتراوح ما يصل إلى مليون فقط بدلا من عشرة آلاف ، دون الوقوع في تجاوزات.هناك حاجة ملحة لذلك ، لنقل نقية مزدوجة الحسابية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top