2012-02-17 20 views
21

Bir dosyayı okumak ve ortalama test puanlarını vermek için bir atamam var.C++ 'da ortalama nasıl edinilir?

Oldukça basit ama ortalamanın nasıl yapıldığını sevmiyorum.

average = (test1 + test2 + test3 + test4 + test5)/5.0; 

Test puanlarının sayısına bölünmesi için bir yol var mı? Kitapta veya google'da böyle bir şey bulamadım. yineleme Via

average = (test + test + test + test)/ntests; 
+0

testlerin sayısı girişini okuyana kadar bilinmemektedir ise, * n * sayıların ortalama yapmak için bir döngü gerekiyordu. – FrustratedWithFormsDesigner

+1

Adım 0: Yığın Taşması'na Taşı. Burada konu yok. –

+4

Mükemmel bir soru ve mükemmel bir gözlem.Hardcoding '5' a) sihirli ve b) gereksizdir. –

cevap

43

, sadece <numeric> den std::accumulate kullanın:

std::vector<double> vec; 
// ... fill vec with values (do not use 0; use 0.0) 
double average = std::accumulate(vec.begin(), vec.end(), 0.0)/vec.size(); 
+0

@RiaD'nin söylediği şeyi detaylandırmak için: Tamsayıları C (++) olarak böldüğünüzde, varsayılan değer yalnızca tamsayı kullanılarak yapılır - ör. Bölme sonuçları kesilir, ondalık noktadan sonra hiçbir veri kalmaz. Veri kümenizin değerleri yeterince büyükse, sorun çok büyük değil, ancak daha küçük sayılarla uğraşırken, bu hassasiyeti kaybetmek istemezsiniz, 0.75 ile düz bir 0'a dönüşebilir. –

+0

Shouldn ' t '0' sadece '0' yerine Çünkü sayı olmadan (-0,5, 0,5), nokta eklemeden sıfır kalır. – ikku100

3

Adım 1. (İsterseniz yapılacak) ve yineleme (eğer basitlik ve hız istiyorsanız) bir diziye bütün test puanları yerleştirmek (cesur olmak istiyorsanız) ya da benzer bir şey bağlantılı liste (esneklik istiyorsanız ancak yavaşsa)

Adım 2. Sonuna ulaşana kadar dizi/liste boyunca yineleyin; Her hücrenin/düğümün içeriğini eklerken. Halihazırda bulunduğunuz hücre/düğümün sayısını da göz önünde bulundurun.

Adım 3. İlk değişkenden toplamı alın ve bulunduğunuz yeri takip eden ikinci değişkene bölün. Bu ortalamayı verecektir. Eğer bir vektör veya bir dizideki değerleri varsa

+0

Bağlantı verilen listenin kullanışlı olması olası değildir. Bu listeyi biraz daha verimli hale getirebilir (ama çoğu vektörün yaptığı gibi aşırı tahsisat yaparsanız, amortize edilmiş karmaşıklık aynıdır), ancak toplanmayı ve uzunluğu daha karmaşık bulmayı sağlar ve 1/3 güzeldir Kötü skor – delnan

+2

Her şey kafamın biraz üstünde. Ben sadece cin cout'u ve diğer birkaç şeyi biliyorum. –

+0

@Jordan O zaman bu, bildiğinizden biraz daha fazlasını öğrenmek için harika bir fırsat sağlayacaktır. Diziler veya listeler ve yineleme, tüm bilgisayar dilleri için temeldir - ne kadar erken öğrenirseniz, o kadar iyidir. – Caleb

1

Ayrıca ortalama hesaplayabilir bağımsız değişken sayısı kullanılarak. Bu ilke, bilinmeyen sayıda argümanın bir yığında saklandığı ve bunları alabildiğimiz bir fonksiyon.

double average(int n, ...)   // where n - count of argument (number) 
{ 
    int *p = &n;     // get pointer on list of number in stack 
    p++;       // get first number 
    double *pp = (double *)p;  // transformation of the pointer type 
    double sum = 0; 
    for (int i = 0; i < n; pp++, i++) //looking all stack 
     sum+=(*pp);     // summarize 
    return sum/n;    //return average 
} 

Ve gibi bu fonksiyonu kullanarak yapabilirsiniz:

double av1 = average(5, 3.0, 1.5, 5.0, 1.0, 2.0); 
double av2 = average(2, 3.0, 1.5); 

Ama argüman sayısı n ile aynı olmalıdır. Ben bunu test

template <typename ForwardIterator, typename F> 
double inline averageOf (ForwardIterator first, ForwardIterator last, F function) { 
    std::vector<typename std::result_of<F(typename ForwardIterator::value_type)>::type> values; 
    while (first != last) { 
     values.emplace_back (function(*first)); 
     ++first; 
    } 
    return static_cast<double>(std::accumulate (values.begin(), values.end(), 0))/values.size(); 
} 

istemci kodu

şöyledir: Burada
+5

Bu kodla dikkatli olun. Uygulama ayrıntılarına bağlı olduğunuzdan, işinizde beklediğiniz gibi garanti edilmez. En azından 64bit makinelerde, argümanlar yoluyla bazı argümanlar geçilmiş, bu kod çalışmayacak. Düzgün uygulamak için, va_start ve co'ya bakın. Ayrıca C++ 11 ile de kullanılabilecek varadic şablonları var. – MJD

0

her değeri almak ve sonra yukarı eklemek için bir lambda fonksiyonu belirterek bir kabın elemanların ortalamasını almak benim genelleştirmesidir
const std::list<CharmedObserver*> devotees = 
    charmer->getState<CharmerStateBase>(CHARMER)->getDevotees(); 
const int averageHitPointsOfDevotees = averageOf (devotees.begin(), devotees.end(), 
    [](const CharmedObserver* x)->int {return x->getCharmedBeing()->getHitPoints();}); 
0

Merak etme, neden kimse boost::accumulators. Zaten yayınlanan çözümlerin en kısa değil, daha genel istatistiksel değerler için daha kolay genişletilebilir. Standart sapma veya daha yüksek anlar gibi.

#include <iostream> 
#include <boost/accumulators/accumulators.hpp> 
#include <boost/accumulators/statistics/stats.hpp> 
#include <boost/accumulators/statistics/mean.hpp> 
#include <algorithm> 
#include <vector> 

double mean(const std::vector<double>& values) { 
    namespace bo = boost::accumulators; 

    if (values.empty()) return 0.; 
    bo::accumulator_set<double, bo::stats<bo::tag::mean>> acc; 
    acc=std::for_each(values.begin(), values.end(), acc); 
    return bo::mean(acc); 
} 

int main() 
{ 
    std::vector<double> test = { 2.,6.,4.,7. }; 
    std::cout << "Mean: " << mean(test) << std::endl; 
    std::cout << "Mean: " << mean({}) << std::endl; 

    return 0; 
} 
0

C++ 11 güzel bir çözüm sunuyor: Bunu böylece otomatik anlamak dönüş türü bunu yazamadı

constexpr auto countArguments() -> size_t 
{ 
    return 0; 
} 

template<class T1, class ... Ti> 
constexpr auto countArguments(T1, Ti ...xi) -> size_t 
{ 
    return 1 + countArguments(xi...); 
} 

template<class T> 
constexpr auto sumAruguments(T x) -> double 
{ 
    return x; 
} 

template<class T1, class ... Ti> 
constexpr auto sumAruguments(T1 x1, Ti ...xi) -> double // decltype(x1 + sumAruguments(xi...)) 
{ 
    return x1 + sumAruguments(xi...); 
} 

template<class...T> 
constexpr auto avarage(T...xi) -> double 
{ 
    return sumAruguments(xi...)/countArguments(xi...); 
} 

. Denediğimde, average(-2) için garip sonuç alıyorum.

https://wandbox.org/permlink/brssPjggn64lBGVq