| Zobacz poprzedni temat :: Zobacz następny temat |
| Autor |
Wiadomość |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
Wysłany: Czw Gru 27, 2007 4:18 pm Temat postu: Funkcja losowania liczb w kodzie C++ |
OCEŃ POST
|
Hej!
Mam jakiegoś babola w kodzie programu, ale nie wychwyciłem gdzie dokładnie tkwi błąd. Kod jest bardzo krótki, oto on:
| c++: |
#include <iostream>
#include <math.h>
using namespace std;
const unsigned IloscLiczb = 6;
const int MaxLiczba = 49;
int main()
{
cout << "________Wybrano losowanie duzego lotka.________\n\n";
cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\ni wyswietla"
" wynik na ekranie. Za kazdym razem wynik losowania jest inny.\n";
"\n\n\nPodaj, ile losowan ma zostac przeprowadzonych: ";
int pola;
cin >> pola;
cin.ignore();
if(pola > 101)
{
cout << "Wybrales " << pola << " losowan. Ze wzgledu na bezpieczenstwo Twojego komputera,\n"
"nie mozna przeprowadzic wiecej niz 100 losowan.\n\n\n\n ";
}
else
{
while(pola)
{
pola = pola - 1;
unsigned Liczby[IloscLiczb];//Od tego momentu algorytm korzysta z dosc znanego tricku - nie tlumacze
for(int i = 0; i < IloscLiczb; ++i) Liczby[i] = 0;
srand(static_cast<int>(time(NULL)));
for (int i = 0; i < IloscLiczb;)
{
Liczby[i] = rand() % MaxLiczba + 1;
bool PowtarzaSie = false;
for(int j = 0; j < i; ++j)
{
if(Liczby[j] == Liczby[i])
{
PowtarzaSie = true;
break;
}
}
if(!PowtarzaSie) ++i;
}
for(int i = 0; i < IloscLiczb; ++i)
cout << " " << Liczby[i];
cout << "\n\n\n";
}
}
system("pause");
}
|
Rzecz w tym, że przy ilości losowań większej niż jedno, wyniki losowań powtarzają się, a powinno być ich tyle ile podał klient. Funkcja losująca jakoś nie jest w stanie wykonywać przy każdym obrocie pętli nowych losowań, tylko powtarza to nieszczęsne pierwsze.
Kompiluje w dev- ie, czy trzeba coś zmienić w pętli while, aby wyniki losowań były różne a nie powtarzały się? _________________ www.lifecode.go.pl |
|
| Powrót do góry |
|
 |
Sinus32
programista

Dołączył: 22 Lip 2007 Posty: 1787 Skąd: z tego cyfrowego świata...
|
Wysłany: Czw Gru 27, 2007 4:54 pm Temat postu: |
OCEŃ POST
|
Trochę poprawiłem - teraz działa jak należy:
| c++: | #include <iostream>
#include <ctime> // Brakujący nagłówek
// Tu był użyty przestarzały nagłówek math.h który nie jest potrzebny
using namespace std;
const unsigned IloscLiczb = 6;
const int MaxLiczba = 49;
int main()
{
srand(static_cast<int>(time(NULL))); // To tu powinno być
cout << "________Wybrano losowanie duzego lotka.________\n\n";
cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\n"
"i wyswietla wynik na ekranie. Za kazdym razem wynik losowania jest"
"inny.\n" // Tu był średnik, a nie powinno go być
"\n\n\nPodaj, ile losowan ma zostac przeprowadzonych: ";
int pola;
cin >> pola;
cin.ignore();
if(pola > 101)
cout << "Wybrales " << pola << " losowan. Ze wzgledu na bezpieczenstwo"
"Twojego komputera,\nnie mozna przeprowadzic wiecej niz 100 losowan.\n\n\n";
else
{
while(pola)
{
pola -= 1; // Optymalniejsze
unsigned Liczby[IloscLiczb];
for(int i = 0; i < IloscLiczb; ++i)
Liczby[i] = 0; // Po co zerujesz? Zaraz je zapełnisz
// Tu był srand wykonywany więcej niż raz w tym kodzie.
// Powodował identyczne wylosowania.
for (int i = 0; i < IloscLiczb;)
{
Liczby[i] = rand() % MaxLiczba + 1;
bool PowtarzaSie = false;
for(int j = 0; j < i; ++j)
{
if(Liczby[j] == Liczby[i])
{
PowtarzaSie = true;
break;
}
}
if(!PowtarzaSie) ++i;
}
for(int i = 0; i < IloscLiczb; ++i)
cout << '\t' << Liczby[i]; // Tak będzie lepiej wyglądać
cout << '\n';
}
}
system("pause");
return 0; // Brakowało, a jest konieczne
} |
Problem był w tym, że srand był wywoływany wielokrotnie w ciągu jednej sekundy i wielokrotnie inicjował generator ciągle tą samą wartością.
Poza tym jeszcze jedna prośba: FORMATUJ KOD |
|
| Powrót do góry |
|
 |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
|
| Powrót do góry |
|
 |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
Wysłany: Pią Gru 28, 2007 8:02 pm Temat postu: |
OCEŃ POST
|
Hej, w związku z już poprawnie działającym algorytmem losowań, wpadł mi do głowy pomysł, aby go jeszcze trochę usprawnić, otóż: kiedy klient wpisze ilość losowań, program wykonuje podaną liczbę losowań, a następnie podaje sześć najczęściej powtarzających się liczb. Chodzi o pewnego rodzaju system znajdowania najbardziej trafnych liczb. Liczb jest 49. Jeśli klient wpisze 70 losowań, taki program wykona je, a na dodatek na końcu wypisze te sześć najczęściej powtarzających się.
System świetny, tylko jak to nawiązać do powyższego, poprawionego przez Sinus32-a kodu?
Próbowałem pokombinować z samą funkcją losującą, ale jest to ponad moje obecne możliwości.
Ma ktoś jakiś pomysł? _________________ www.lifecode.go.pl |
|
| Powrót do góry |
|
 |
Sinus32
programista

Dołączył: 22 Lip 2007 Posty: 1787 Skąd: z tego cyfrowego świata...
|
|
| Powrót do góry |
|
 |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
|
| Powrót do góry |
|
 |
Sinus32
programista

Dołączył: 22 Lip 2007 Posty: 1787 Skąd: z tego cyfrowego świata...
|
|
| Powrót do góry |
|
 |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
Wysłany: Sob Gru 29, 2007 8:58 pm Temat postu: |
OCEŃ POST
|
Ok, lol, kod potężnie przebudowany.
| c++: |
if(IleLosowan > 5000) IleLosowan = 5000; // Trochę podniosłem górny limit
if(IleLosowan < 1) IleLosowan = 1; |
Rzeczywiście, dzięki temu nie trzeba puszczać głupiego komunikatu. Jestem ciekaw ile można by było ustawić najw. liczbę losowań, tak aby komp klienta nie oszalał?
| c++: | Licznik[i] = new licznik;
Licznik[i]->co = i + 1;
Licznik[i]->ile = 0; |
Ok, ale co oznacza gdy piszesz: Nie widziałem takiego zapisu?
| c++: | void sortuj(licznik**, unsigned short); |
Co robią te dwie gwiazdki po "licznik" i co daje to, że jest on typu "struct"? _________________ www.lifecode.go.pl |
|
| Powrót do góry |
|
 |
Sinus32
programista

Dołączył: 22 Lip 2007 Posty: 1787 Skąd: z tego cyfrowego świata...
|
|
| Powrót do góry |
|
 |
Dante190884

Dołączył: 03 Paź 2007 Posty: 19 Skąd: Kraków
|
Wysłany: Nie Gru 30, 2007 1:57 pm Temat postu: |
OCEŃ POST
|
Ok, zaimplementowałem Twój kod do swojego kalkulatora, choć nie było łatwo, bo wystąpiły problemy z funkcją "sortuj". Ponieważ menu mam realizowane za pomocą "switch", w case xx funkcja nie dała się skompilować.
Przeniosłem więc ją do instrukcji "if" i teraz w skrócie to wygląda tak:
| c++: |
//DEFINICJE I DEKLARACJE DO DUŻEGO LOTKA*********************************************************************************
const unsigned short IloscLiczb = 6;// Ilość liczb wylosowanych w dużym lotku.
const unsigned short MaxLiczba = 49;// Losowanie w dużym lotku spośród 49 liczb.
struct licznik
{
int co;
int ile;
};
void sortuj(licznik**, unsigned short);
fun. main:
switch(wybor)
....
....
....
if(wybor == 14)
{
system("cls");
srand(static_cast<int>(time(NULL)));// W losowaniu lotto potrzebny do wykonania losowania wielokrotnie.
cout << "________________Wybrano losowanie duzego lotka.________________\n\n";
cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\n"
"i wyswietla wynik na ekranie. Za kazdym razem wynik losowania jest"
" inny.\nPonadto wyswietla min. szesc najczesciej powtarzajacych sie liczb.\n\n"
"\nPodaj, ile losowan ma zostac przeprowadzonych: ";
unsigned short IleLosowan;
cin >> IleLosowan;
if(IleLosowan > 50000) IleLosowan = 50000; // Optymalna liczba losowań. Jak klient wpisze
if(IleLosowan < 1) IleLosowan = 1; // większą, to i tak zostanie wykonanych max. 50 000.
unsigned short Liczby[IloscLiczb];
licznik * Licznik[MaxLiczba];
for (int i = 0; i < MaxLiczba; ++i)
{
Licznik[i] = new licznik;
Licznik[i]->co = i + 1;//Operator -> jest operatorem dostępu pośredniego (przez wskaźnik).
Licznik[i]->ile = 0;
}
for(unsigned short Losowanie = 0; Losowanie < IleLosowan; ++Losowanie)
{
for (int i = 0; i < IloscLiczb; ++i)
{
Liczby[i] = rand() % MaxLiczba + 1;
for(int j = 0; j < i; ++j) if(Liczby[j] == Liczby[i]) {--i; break;}
}
for(int i = 0; i < IloscLiczb; ++i)
{
++(Licznik[Liczby[i] - 1]->ile);
cout << '\t' << Liczby[i];
}
cout << '\n';
}
sortuj(Licznik, MaxLiczba);
int min = Licznik[5]->ile;
cout << "Najczesciej powtarzajace sie liczby to:\n\n";// Wyświetla minimum 6 najczęściej wylosowanych liczb
for(int i = 0; i < MaxLiczba; ++i)
{
if (Licznik[i]->ile >= min)
cout << "Liczba " << Licznik[i]->co << " wypadla " << Licznik[i]->ile << " razy\n\n";
delete Licznik[i];
}
}
}
void sortuj(licznik ** Dane, unsigned short Granica)
{
licznik * temp;
unsigned short int i, j;
Granica--;
for(i = 0; i < Granica; i++)
for(j = 0; j + i < Granica; j++)
if(Dane[j]->ile < Dane[j+1]->ile)
{
temp = Dane[j];
Dane[j] = Dane[j+1];
Dane[j+1] = temp;
}
}
//koniec***************************************************
|
Wszystko działa wyśmienicie, niestety nie jestem w stanie jeszcze zrozumieć zasadniczego działania. Ponieważ jest to zrealizowane za pomocą "tricków", których jeszcze nie znam, nie mogę nawet pobawić się nad modyfikowaniem tego kodu (bo pewnie bym popsuł). A chciałem jeszcze dodać jedną rzecz: otóż po wylosowaniu i wybraniu najczęściej powtarzających się liczb, algorytm mógł by wypisać na ekranie tylko te liczby, które ani razu nie zostały wylosowane spośród wszystkich losowań.
Nie wiem, czy to trudne i czy trzeba będzie mocno zmodyfikować/dodać kod? _________________ www.lifecode.go.pl |
|
| Powrót do góry |
|
 |
Sinus32
programista

Dołączył: 22 Lip 2007 Posty: 1787 Skąd: z tego cyfrowego świata...
|
Wysłany: Nie Gru 30, 2007 3:31 pm Temat postu: |
OCEŃ POST
|
Modyfikacja była by bardzo prosta. Była by w tej części kodu:
| c++: | for(int i = 0; i < MaxLiczba; ++i)
{
if (Licznik[i]->ile >= min)
cout << "Liczba " << Licznik[i]->co << " wypadla " << Licznik[i]->ile << " razy\n\n";
// Tutaj <----------------------------------
delete Licznik[i];
} |
Tablica wskaźników Licznik zawiera MaxLiczba rekordów w których są zapisane liczby i ilość ich wystąpień. |
|
| Powrót do góry |
|
 |
|
|
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach
|
hosting sponsorowany przez hosted.pl
Powered by phpBB © 2001, 2002 phpBB Group
|