» »

[C++] Functor za izračun osnovne statistike podatk. strukture (vector,list...)

[C++] Functor za izračun osnovne statistike podatk. strukture (vector,list...)

zhigatsey ::

Živjo,

Tukaj, je moj problem Slogamedev.net

Pa še noob question:
A mi kdo lahko pove kako, naj označim mojo c++ kodo za tale primer v tem forumu da mi ne bo skozi javljalo uporaba neveljavne html
oznake recimo za #include iostream (seveda manjkajo tisti znaki za manjše večje, ker bi drugače spet javilo napako:) ) potem bom še sem prilepil še kodo, da ne bo treba na slogamedev.:\

Sej veste bolje biti neumen 5 minut kot pa celo življenje...:D

kopernik ::

Že x-tič: preberi si tale članek

hint: obdaj svojo kodo s [ st.koda] tagom

zhigatsey ::

Med članke pa res nisem šel gledat:)
No tukaj je problem in koda

Za hitri izračun statistike v STL podatkovnih strukturah kot so vector,
list itd. sem naredil functor, ki na enostaven način to naredi. Ker bi
rad preračunaval več številskih tipov(int, double, long...) sem uporabil template-e.

// TarSumaryStat
template<class T>
class TarSummaryStat {
    private:
        size_t FNum; // Število elementov
        T FSum;      // Vsota elementov
        T FMin;      // Najmanjši element   
        T FMax;      // Največji element
    public:
        TarSummaryStat() : FNum(0),
                           FSum(0),
                           FMin(0),
                           FMax(0) {};    // Ctor
       
        // "function call"
        // process one more element of the sequence
        void operator() (T elem)
        {
            FNum++;         // inkrementalno štetje elementov
            FSum += elem;   //add value
           
            // Initialization of FMin and FMax with first element
            if (FNum == 1)
            {
                FMin = elem;
                FMax = elem;
            };
           
            if (elem < FMin) { FMin = elem; }
            if (elem > FMax) { FMax = elem; }
        };
       
        // return number of elements
        size_t count() { return FNum; };
       
        // return averege of values
        T average() { return arsavedivide(FSum, FNum); };     
       
        // return sum of values
        T sum() { return FSum; };   
       
        // return  min of values
        T min() { return FMin; };
       
        // return  max of values
        T max() { return FMax; };
       
        // return range of values
        T range() { return FMax - FMin; }
};


Za izračun povprečja, uporabljam funkcijo arsavedivide, ki je tudi narejena s pomočjo templateov.

// arsavedivide (Preprečuje deljenje z 0)
template<class T>
inline T arsavedivide(T first, T second)
{
    return ( second != 0 ? (first / second) : 0 );
}


Ta objekt pa potem uporabim na slednji način recimo za vrednosti tipa double:

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;

int main(int argc, char *argv[])
{
  vector<double> values;
 
  for (int i = 0; i < 7; i++)
  {
    values.push_back(i);
  }
 
  TarSummaryStat<double> st = for_each( values.begin(), values.end(), TarSummaryStat<double>() ); 

  cout << "count: " << st.count() << endl;
  cout << "sum: " << st.sum() << endl;
  cout << "average: " << st.average() << endl;
  cout << "min: " << st.min() << endl;
  cout << "max: " << st.max() << endl;
  cout << "range: " << st.range() << endl;
 
  system("PAUSE");   
  return 0;
}



Seveda pride do napake pri računanju povprečja, zato ker je v razredu TarSummaryStat privatna
spremenljivka FNum, ki predstavlja število elementov v kontajnerju, tipa
size_t, FSum, ki predstavlja vsoto elementov pa je tipa T oz. double.
Tako program poči pri funckciji arsavedivide, saj sta parametra različnih tipov, razen če objekt ne uporabim z podatki tipa size_t (
TarSummaryStat<size_t>
) Torej kako naj naredim, da bo delovalo pravilno. Pri uporabi templateov sem še zelen tako da nevem če sem ga kaj v kamen s temle razredom. Če mi lahko kako svetujete.

Hvala za odgovore

Gundolf ::

Enostavno, vedno delis z integerjem (oziroma size_t, ki spada med integerje).

template<class T>
inline T arsavedivide(T first, size_t second) 
{
    // second pretvoris v isti tip da ne vrne warningow
    // v vecini primerov bi delovalo tudi avtomatsko
    return ( second != 0 ? (first / (T)second) : 0 );
}


Pa da se pokomentiram nekaj kar sem opazil v kodi.
TarSummaryStat<double> st = for_each( values.begin(), values.end(), TarSummaryStat<double>() ); 

to bi moralo biti
TarSummaryStat<double> st;
for_each( values.begin(), values.end(), st ); 

Drugace izgubis vse kar si izracnal s funktorjem, saj ta obstaja le znotraj for zanke. Spremenljivka St pa se vmes nic ne spremeni, razen tega da ji dolocis vrednost, ki jo vrne foreach. Za tega pa res ne vem na pamet kaj sploh vre. Morda stevilo iteracij zanke? V bistvu mi sploh ni jasno zakaj ti tu ne vrne se kaksnega errorja (morda ti ga pa nisi omenil).

zhigatsey ::

to bi moralo biti
TarSummaryStat<double> st;
for_each( values.begin(), values.end(), st ); 


Če naredim na ta način mi st ne vrne nobenega rezultata oz. so povsod nule.
Drugače pa sem ga pomoje u kamen s temi templatei, ker mi pri računanju z integer vrednostmi,
average vrne tudi integer.

BigWhale ::

Problem bos enostavno resil tako, da bos template definiral takole:

template<class T, class U>
inline T arsavedivide(T first, U second)
{
    return ( second != 0 ? (first / second) : 0 );
}



PS: st,koda tag je pathetic excuse for a tag,...

Zgodovina sprememb…

  • spremenilo: OwcA ()

Gundolf ::

Ja a noces imeti povprecja istega tipa kot so elementi? Lahko seveda spremenis tip arsavedivide tako da bo vedno delal z doubli (nic vec template). Samo tak ti potem ne bo vec delal na recimo kompleksnih stevilih.

Sem pa zdaj pogledal kaj vrne for_each in imas cisto prav. Vrne namrec kopijo funktorja, ki mu ga podas kot tretji parameter. In tudi moja ideja, da bi mu podal kot tretji parameter kar st je napacna, saj v tem primeru naredi le njegovo kopijo, ki pa jo nato spet izgubi takoj po koncu for_each funkcije. Tvoj nacin je torej cisto pravilen :)

BigWhale ::

PS seveda bo prislo do cudnih rezultatov, ce bos primerjal char* in int recimo. Takrat bos moral pa napisat 'specialno' predlogo (template specialization)

:)

zhigatsey ::

Ma ja sej zamisel s temi templatei je bla kar dobra, vendar jih moram se malo prestudirat.
Drgac je pa kriza z average, ker ce mas integerje v kontajnerju recimo (5, 9, 6), bo funkcija vrnila
6 in ne 6.6666... Tko, da ne vem glih kaj naj naredim.

Vesoljc ::

ja sej ti je bw povedu, da mu lahko tud tip povprečja podaš. ko jih seštevaš jih cast-aš v željeni tip ter na koncu deliš...
Abnormal behavior of abnormal brain makes me normal...


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

C - shranjevanje rezultatov iz baze v array

Oddelek: Programiranje
71191 (890) Randomness
»

[C] LPC1343 - UART - AT commands

Oddelek: Programiranje
91075 (965) JanezovJanez
»

[Java - DN] Naključna števila

Oddelek: Šola
121335 (864) nyler
»

vector::iterator problemi, brisanje podatkov iz vektorja

Oddelek: Programiranje
81088 (939) mn
»

[C++] Thinking in C++

Oddelek: Programiranje
101100 (965) rozha

Več podobnih tem