CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - SMA - poddaje się

SMA - poddaje się

dział ogólny

SMA - poddaje się

Nowy postprzez Corvis » środa, 12 stycznia 2011, 23:47

Witam,

Wyczerpałem już chyba wszystkie swoje szare komórki odnośnie tego problemu - jest on banalnie prosty, jednak mój mózg nie może tego ogarnąć - jakaś zaćma nastała :(

1. Mam do wyliczenia średnią SMA ( http://pl.wikipedia.org/wiki/%C5%9Arednia_krocz%C4%85ca )
2. Dane do średniej mam w wektorze Dane
3. Liczę to tak:

KOD cpp:     UKRYJ  
std::vector<int> Dane;
std::vector<double> WartoscSredniej;
int okres = 10; // Wartosc okresu średniej
double suma = 0;
double val = 0;
int Max = 0;
for(int t = 0; t < Dane.size(); t++) {
        Max = t + okres;
        if(Max>Dane.size()) Max = Dane.size()-1;

        while(Max!=t) {
                val = Dane[Max];
                suma+=val;
                Max--;
        }

        WartoscSredniej[t] = suma/okres;
        suma=0;
}
 


Może mi ktoś powiedzieć czy:

1. to jest dobry sposób ??
2. da się to przyśpieszyć bo chodzi słabo przy dużych okresach :-(
3. Czy wogóle dobrze liczę tą średnią ??


Z góry proszę o wyrozumiałość - ale czasami na najprostszych rzeczach można się położyć :roll:
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez Cyfrowy Baron » czwartek, 13 stycznia 2011, 11:12

Jak rozumiem prosta średnia krocząca SMA to suma okresów podzielona przez liczbę okresów, czyli:

SMA = (P0 + P1 + P0 + ... + Pn) / Pn

Przykładowo jest 6 okresów: 10; 15; 20; 25; 30; 17, czyli SMA obliczam w ten sposób:

SMA = (10 + 15 + 20 + 25 + 30 + 17) / 6 = 19.5

Jeżeli tak to proponowałbym wykorzystać rekurencję:

KOD cpp:     UKRYJ  
#include <vector.h>

using namespace std;

//---------------------------------------------------------------------------
int sum(vector<double> P, int size)
{
  if(size < 0) return 0;

  return P[size] + sum(P, size - 1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSMAClick(TObject *Sender)
{
 vector<double> P;
 P.push_back(10);
 P.push_back(15);
 P.push_back(20);
 P.push_back(25);
 P.push_back(30);
 P.push_back(17);

 double n = P.size();
 double SMA = sum(P, n - 1) / n;

 EditSMA->Text = (String)SMA;
}

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Corvis
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » czwartek, 13 stycznia 2011, 11:24

Dzięki, sprawdzić to będę mógł dopiero wieczorem - bo teraz nie mam przy sobie programu który wykorzystuje te średnie. Sprawdzę i dam znać


Edit:

SMA = (10 + 15 + 20 + 25 + 30 + 17) / 6 = 19.5

To wygląda jak zwykła arytmetyczna średnia a nie krocząca.

to chyba trzeba policzyć dla każdego elementu: dla okresu = 2

10 = (15+10)/2

15 = (20+15)/2

20 = (25+20)/2

25 = (30+25)/2

30 = (17+30)/2

17 = 17 ??

Szkoda, że nie mam tego programu swojego.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez Cyfrowy Baron » czwartek, 13 stycznia 2011, 11:38

Przeglądałem przykład w sieci dla SMA i było tam napisane tak jak podałem.

http://www.twojbiznes.org/narzedzia-srednie_ruchome.htm

To wygląda jak zwykła arytmetyczna średnia a nie krocząca.


W linku do wikipedii który podałeś jest wyraźnie napisane: Prosta średnia krocząca (ang. simple moving average, SMA) to zwykła średnia arytmetyczna wartości z ostatnich n okresów.

czyli zgadza się, SMA to zwykła średnia arytmetyczna.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » czwartek, 13 stycznia 2011, 23:27

No ale za pomocą funkcji którą podałeś nie jesteś w stajnie uzyskać takiego wykresu jak w linku.

Mając wartości np.

10
15
20
25
30
17

i wywołując twoją funkcję to będę miał jedną i tą samą wartość wartość tylko.

a żeby wykres narysować to muszę mieć wartości dla każdej z wyżej podanych liczb. 10,15, 20,25,30,17

Nie wiem o co chodzi - ale naprawdę tego nie rozumiem. :roll: :(

Taki wykres otrzymałem (nie wiem czy dobry) licząc to takim kodem jaki podałem na początku, ale dla dużych okresów komputer umiera :|
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez Cyfrowy Baron » piątek, 14 stycznia 2011, 10:15

Taki wykres otrzymałem (nie wiem czy dobry) licząc to takim kodem jaki podałem na początku, ale dla dużych okresów komputer umiera :|


By uniknąć powtarzania wciąż tych samych działań musisz zastosować rekurencję.



i wywołując twoją funkcję to będę miał jedną i tą samą wartość wartość tylko.


Przecież podana przeze mnie funkcja, tylko sumuje wartości, jeżeli musisz pobierać wartość dla każdego okresu to wystarczy wywoływać tą funkcję n razy. Nie pomyślałeś o tym? :o

KOD cpp:     UKRYJ  
#include <vector.h>

int sum(vector<double> P, int size)
{
  if(size < 0) return 0;

  return P[size] + sum(P, size - 1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSMAClick(TObject *Sender)
{
 vector<double> P;
 P.push_back(10);
 P.push_back(15);
 P.push_back(20);
 P.push_back(25);
 P.push_back(30);
 P.push_back(17);

 vector<double> graphPoint;

 double n = P.size();

 for(int i = 1; i <= n; i++)
 {
  double SMA = sum(P, (double)i - 1) / (double)i;

  graphPoint.push_back( SMA );

  ListBox1->Items->Add( FloatToStr(SMA) ); // tylko celem sprawdzenia
 }
}


Jak to działa?

KOD text:     UKRYJ  
SMA1 = 10 / 1
SMA2 = (10 + 15) / 2
SMA3 = (10 + 15 + 20) / 3
SMA4 = (10 + 15 + 20 + 25) / 4
SMA5 = (10 + 15 + 20 + 25 + 30) / 5
SMA6 = (10 + 15 + 20 + 25 + 30 + 17) / 6
Kod nie jest jednak optymalny gdyż funkcja jest wywoływana wielokrotnie a nie ma takiej potrzeby. Spróbuję to zoptymalizować.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Corvis
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Cyfrowy Baron » piątek, 14 stycznia 2011, 12:28

Poprzedni kod wykorzystuje rekurencję tylko do sumowania, a wykonanie obliczeń SMA dla 6 okresów wymaga aż 21 cykli. Teraz przedstawiam kod wykorzystujący rekurencje do wyliczenia całej średniej arytmetycznej SMA i kod dla 6 okresów wykona dokładnie tyle cykli, czyli 6.
KOD cpp:     UKRYJ  
/*
SMA1 = 10                            = 10  / 1 = 10;
SMA2 = (10 + 15)                     = 25  / 2 = 12.5
SMA3 = (10 + 15 + 20)                = 45  / 3 = 15
SMA4 = (10 + 15 + 20 + 25)           = 70  / 4 = 17.5
SMA5 = (10 + 15 + 20 + 25 + 30)      = 100 / 5 = 20
SMA6 = (10 + 15 + 20 + 25 + 30 + 17) = 117 / 6 = 19.5
*/

void sum(const vector<double> P, vector<double> &graphPoints, double size, double value)
{
  if(size >= P.size()) return;

  double s = size + 1;

  value = value + P[size];

  double sma = value / s;

  graphPoints.push_back( ( sma ) );

  sum(P, graphPoints, s, value);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSMAClick(TObject *Sender)
{
 vector<double> P;
 P.push_back(10);
 P.push_back(15);
 P.push_back(20);
 P.push_back(25);
 P.push_back(30);
 P.push_back(17);

 vector<double> graphPoints;

 sum(P, graphPoints, 0, 0); /* argument size musi mieć wartość 0 jeżeli liczenie ma się odbywać od początku, value zawsze musi mieć 0 */

 /* sprawdzam co zawiera vektor graphPoint  */
 for(int i = 0; i < graphPoints.size(); i++)
 {
  ListBox1->Items->Add( FloatToStr( graphPoints[i] ) );
 }
}


Dla tysiąca okresów o niedużych wartościach kod wykonał się w 50 ms, ale przy większej liczbie okresów pojawia się problem z pojemnością zmiennej double. Ma za małą pojemność i nie jest w stanie wyliczyć większych wartości. Typ long double ma rozmiar 80 bitów, ale dla 5000 okresów o wartości 2 każdy było to za dużo, chyba że to ograniczenie w pojemności vector'a. W każdym bądź razie przy dużych liczbach otrzymuję komunikat stack overflow - przepełnienie stosu, więc coś się nie mieści.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » sobota, 15 stycznia 2011, 17:38

Czyli, tutaj okresem jest rozmiar wektora wejściowego ?? Jak dodam jeszcze jedną wartość to będę miał SMA7 itp.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez Corvis » niedziela, 16 stycznia 2011, 01:46

KOD cpp:     UKRYJ  
// std::vector<double> WartosciTikow; // tak wygląda deklaracja wartosci ze struktury Tik

void LiczSMA2(std::vector<Tik> &Dane, int AdresSMA, int AdresWyniku, int okres, long suma) {
        static int ile = 0;
        static int wsk = 0;

        if((wsk+ile) >= Dane.size()) {
                wsk = 0;
                ile = 0;
                return;
        }

        bool zmiana = false;

        if(ile == okres) {
                ile = 0;
                Dane[wsk].WartosciTikow[AdresWyniku] = suma/okres;
                suma = 0;
                wsk++;
                zmiana = true;
        } else {
                suma+=Dane[wsk+ile].WartosciTikow[AdresSMA];
        }

        if(!zmiana) ile++;

        LiczSMA2(Dane, AdresSMA, AdresWyniku,okres,suma);
}
 



Napisałem kod który generuje prawidłowe wyniki i wykresy, jest tylko jeden problem działa dobrze dla okresów 1,2,3,4 -> jeżeli zwiększe okres na 5 i wyżej mam komunikat STACT OVERFLOW , za groma nie mogę znaleść błędu :| ( chyba już późna pora )


Ps.Funkcja wygląda słabo (nazwy i sposób napisania i typy zmiennych) ale miała na celu sprawdzić czy dobrze się wykres wygeneruje.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez polymorphism » niedziela, 16 stycznia 2011, 12:22

Użyj debuggera.

Po co w ogóle ta rekurencja, przecież można to zrobić metodą iteracyjną?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » niedziela, 16 stycznia 2011, 12:34

Debugger pokazuje że to wywołanie funkcji LiczSMA2 - i, że jest to raz 166 wywołanie raz 1000 więc nic mi to nie mówi.

Czemu rekurencja ? Wzorowałem sie na kodzie cyfrowego barona. W 1 poście podałem kod nie rekurencyjny ale strasznie wolno chodził.
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez polymorphism » niedziela, 16 stycznia 2011, 13:02

Co, przepełnienie stosu przy 166 wywołaniu?! Przecież to zaledwie ~16KB stosu. Coś tu nie gra...
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » niedziela, 16 stycznia 2011, 13:06

Sam nie wiem o co chodzi, myślałem, że to może deklarowanie tych static w funkcji ale zmieniłem to i błąd też jest
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Re: SMA - poddaje się

Nowy postprzez polymorphism » niedziela, 16 stycznia 2011, 13:25

Hmm, dziwne to wszystko...

Upraszczając nieco zapis funkcji:
KOD cpp:     UKRYJ  
void LiczSMA2(std::vector<Tik> &Dane, int AdresSMA, int AdresWyniku, int okres, long suma)
{
        static int ile = 0;
        static int wsk = 0;

        if((wsk + ile) >= Dane.size()) //<---
        {
                wsk = ile = 0;
                return;
        }

        if(ile == okres)
        {
                Dane[wsk].WartosciTikow[AdresWyniku] = suma / okres;
                ile = suma = 0;
                ++wsk; //<---
        }
        else
        {
                suma += Dane[wsk + ile].WartosciTikow[AdresSMA];
                ++ile; //<---
        }

        LiczSMA2(Dane, AdresSMA, AdresWyniku,okres,suma);
}
 

Widać, że nie ma takiej opcji, żeby pierwszy warunek w którymś momencie nie przerwał rekurencji. Albo coś umyka mojej uwadze, albo błąd leży zupełnie gdzieś indziej.

--- dodane ---

W sumie najlepiej będzie, jeśli przerobisz kod na wersję iteracyjną, ponieważ wersja rekurencyjna i tak będzie podatna na przepełnienie stosu, szczególnie gdy ilość danych wejściowych będzie szła w setki tysięcy.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: SMA - poddaje się

Nowy postprzez Corvis » niedziela, 16 stycznia 2011, 14:35

Dzięki za odp, ale niestety ten kod też powoduje błąd przepełnienia stosu :(

Możesz zerknąć na ten kod z 1 posta w tym wątku ?? on działa dobrze tylko mega wolno
"Sukcesy trwają, dopóki ich ktoś nie spieprzy. Porażki są wieczne"

Dr Gregory House
Avatar użytkownika
Corvis
Programista I
Programista I
 
Posty: 880
Dołączył(a): sobota, 26 lipca 2008, 00:31
Podziękował : 80
Otrzymał podziękowań: 30
System operacyjny: WINDOWS 7 64-bity
Kompilator: Praca - C++ Builder XE2 ENTERPRISE - Update 4, Dom - C++ Builder XE4 - Uddate 1
Gadu Gadu: 0
    Windows VistaChrome

Następna strona

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 5 gości