[c++] histogram

Awatar użytkownika
lightinside
Użytkownik
Użytkownik
Posty: 796
Rejestracja: 25 lis 2011, o 22:25
Płeć: Kobieta
Lokalizacja: Poznań/Łódź
Podziękował: 111 razy
Pomógł: 29 razy

[c++] histogram

Post autor: lightinside »

Mam problem, z histogramem źle pokazuje same zera, program tak wogle służy do rozkładu normalnego, i robi taki bład ze jak napisze sie za dużo liczb to jakoś dziwnie pomija niektóre liczby, i sie zacina w pewnym momencie na jakies 2-3 sekundy, potem normalnie działa.

Sądze ze mże to być problem z pętlami i tablicami ale ja nie widze błędów

Prosze o pomoc i poprawe kodu;)

Kod: Zaznacz cały

#include <iostream>
#include <cstdlib>  // rand(), rand() and RAND_MAX
#include <cmath>  // sqrt(), log() and sin()
#include <time.h>  // time()
#include <fstream> //obsuga plikow

double normal();
using namespace std;
double poj[10000][10000];//przechowuje nr roznych klas i elementow x tak by dla kazdego wiersza (dana klasa)przypadala dana liczba kolumn ktora okresla poszczegolne x ktore tam wpadly
double min_kl[10000];
int main(void)
{
    int i,j,k,l,m,u,w;//indeksy
    double max,min,modul_min,szer_gl,liczba_kl;//
    double tablica_na_x[10000];//przechowuje wylosowane x 
    double max_kl[10000];//przechowuje max dla danej klasy
    double x,suma=0,suma_kwadratow=0,z;
    int ilosc;//ilosc x
    double szer_kl;//szerokosc pojedynczej klasy,stala dla wszystkich klas
    char nazwa[20];//przechowuje nazwe pliku 
    srand((unsigned) time(NULL));//inicjalizacja "ziarna"

    void sort(double &, double &, double &);//odpowiada za sortowanie
    void klasy( double , double  , double );


    cout<<"Podaj nazwe pliku do ktorego chcesz zapisac wyniki (.txt na koncu): ";
    cin>>nazwa;
    ofstream fout(nazwa);//otworzenie pliku do zapisu
    cout<<"Podaj ilosc liczb do wylosowania (0 konczy): ";
    cin>>ilosc;
    while(ilosc!=0) //ilosc kończy... ale nigdzie się nie zmienia;/ czyli jak podam ilosc inna niz 0 to będzie w nieskonczonosc pracowac...
    {
      suma=0;
      suma_kwadratow=0;


      for(i=0;i<ilosc;++i)
      {
          x=normal();//losuje losowe liczby x
          suma+=x;
          suma_kwadratow+=(x*x);
          cout <<x <<endl; 
          tablica_na_x[i]=x;
      }

      // min == max == pierwsza wylosowana liczba losowa
      min=tablica_na_x[0];
      max=tablica_na_x[0];

      for(int i=0;i<=ilosc;i++)
      {
        sort(max,min,tablica_na_x[i]);
      }
      szer_kl=0.16*sqrt(suma_kwadratow/ilosc-(suma/ilosc)*(suma/ilosc));
      modul_min = fabs(min);
      szer_gl=-modul_min + max;
      liczba_kl=szer_gl/szer_kl;


  klasy(modul_min ,szer_kl ,max);
 
  double zlicz[1000]; // każdy element tablicy to  słupek histogramu...
  //czyli jak jakis element z tablicy na x jest zaliczany do np. do 4 klasy to  zlicz[4] ++;
  for(int i=0;i<1000;i++)
  {
    zlicz[i] =0; // najpierw zerujemy wszystkie klasy
  }

  // teraz bierzemy element z tablicy na x i patrzymy do której klasy należy...
  // czyli bierzemy zerową klase i sprawdzamy if'em jak nie należy to następna klasa i tak aż znajdziemy lub skończą się klasy...
  for(int i=0;i<=ilosc;i++) // petla po ilosci bo sprawdzamy kazdy element z tablicy na x
  {
    int nr=0; // to bedzie numer klasy...
    bool end;
    do  
    {
      end = false;
      //jesli element wiekszy lub równy min danej klasy i jednocześnie mniejszy od min następnej to zaliczamy go do tej klasy...
      // przedziały klas domknięte prawostronnie to znaczy element z tablicy na x należy do przedziału < min[nr] ,min[nr+1] )
      if( tablica_na_x[i] >= min_kl[nr] && tablica_na_x[i] < min_kl[nr+1])
      {
        zlicz[nr]++; // jak warunek spełniony to zaliczamy element do tej klasy
        end =true;     // i konczymy poszukiwania... przechodzimy do następnego elemetu z tablicy na x
      }
      else nr++;      // jak nie zaliczony to zwiększamy nr klasy
      if(nr > liczba_kl ) end =true; // jak nr wiekszy niż liczba klas to kończymy
    }while( !end );   // powtarzamy "do" doupuki end jest false...
    FILE *plik;
    plik = fopen("hist.txt", "w");

for(int nr = 0; nr < 1000; nr++)
{
fprintf(plik, "%d ", zlicz[nr]);
}

fclose(plik);
  }
for(u=0;u<ilosc;u++)
{
for( w=0;w<liczba_kl;w++)
{
  if( tablica_na_x[u] >= min_kl[w] && tablica_na_x[u] < min_kl[w+1])
  {poj[w][u]=z; cout<<"\n Element "<<u<<" nalezy do klasy"<<w; 
  FILE *plik = fopen("hist2000.txt", "w");fprintf(plik, "%d ", poj[w][u]);fclose(plik);
   }
  
}
}

 FILE *plik = fopen("hist2000.txt", "w");

for(int u = 0; u <= 1000; u++)
{
for(int w = 0; w <= 1000; w++) 
{       
fprintf(plik, "%d ", poj[w][u]);
}

fclose(plik);
  }
      cout<<"\n=======================================================================\n";
      cout<<"Wartosc max              = "<<max<<endl;
      cout<<"Wartosc min              = "<<min<<endl;
      cout<<"Liczba klas                "<<liczba_kl<<endl;
      cout<<"Roznica miedzy max i min = "<<szer_gl<<endl;
      cout<<"Ilosc wylosowanych liczb = "<<ilosc<<endl;
      cout<<"Srednia arytmetyczna to: = "<<suma/ilosc<<endl;
      cout<<"Wariancja wynosi:        = "<<suma_kwadratow/ilosc-(suma/ilosc)*(suma/ilosc)<<endl;
      cout<<"Odchylenie standardowe to = "<<sqrt(suma_kwadratow/ilosc-(suma/ilosc)*(suma/ilosc))<<endl;
      cout<<"Szerokosc pojedynczej klasy wynosi = "<<szer_kl<<endl;
      cout<<"\n========================================================================\nPodaj ilosc liczb do wylosowania (0 konczy): ";
      cin>>ilosc;
    } //while end...
  fout.close();//zamknij plik
  return 0;
}

// losuje liczby o rozkladzie normalnym o zadanej sredniej i odchyleniu standardowym
double normal() //metoda Transformacji Boxa-Mullera
{
  static const double pii=3.141592654;
  static const double r_max=RAND_MAX+1;
  static float odchylenie=1, srednia=1;
  return odchylenie*sqrt(-2*log((rand()+1)/r_max))*sin(2*pii*rand()/r_max)+srednia;
}

void sort(double &a, double &b, double &c)
{
  // a to max, b to min, c to element z tablicy o nazwie "tablica_na_x"
  if( c>a ) a=c; // jesli element z tablicy jest większy od max to zapisuje ten element jako max
  if( c<b ) b=c; // jesli element z tablicy jest mniejszy od min to zapisuje go jako min
}

void klasy( double min , double szerokosc , double max)
{
  /* liczba klas to (|min|+max)/szer klasy
   * to gdy wezmiemy poczatek histogramu na |min|
   * i bedziemy dodawac szerokosc klasy
   * to po wykonaniu takiej operacji tyle razy ile jest klas otrzymam max
   * czyli inaczej mowiac minimalna wartosc w histogramie to mod_min
   * szerokosc slupka histogramu to szer_kl
   * czyli pierszy slupek konczy sie mod_min + szer_kl... i wszystko co wieksze nalezy do nastepnego slupka histogramu
   * i tak dalej... przyjme że gdy liczba jest na granicy przedziału to nalezy do klasy wyzej czyli
   * np. gdy x = mod_min + szer_kl to program wpisze x do drugiego słupka*/


    int nrkl =0;                                    // numer klasy histogramu
   min_kl[nrkl] =min;                                 // minimalna wartosc w danej klasie
   do
   {
     nrkl +=1;                                      // przechodizmy do nastepnej klasy
     min_kl[nrkl] = min_kl[nrkl-1] + szerokosc;     // minimum poprzedniej klasy + szerokosc to minimum bierzacej klasy
   }while( min_kl[nrkl] < max );                   // robimy tak dlugo az dostaniemy maksa histogramu...
}

ODPOWIEDZ