Nowe posty

xx Problem ze sterownikami. (5)
2024-04-13, 21:25:16
xx Instalacja xfce4 (2)
2024-04-13, 16:20:17
xx Serie kompilacji bez instalacji dla “emerge” w Gentoo (2)
2024-04-08, 18:40:04
xx Plasma 6 w Neonie ssie trochę mniej ... (17)
2024-04-05, 10:03:46
xx Problem z Linux Lite po instalacji (3)
2024-04-03, 14:23:40
xx Jak właczyć num locka przy starcie systemu debian 12? (12)
2024-04-02, 17:43:54
xx Brak dźwieku w systemie. (5)
2024-04-02, 16:13:41
xx Dystrybucja pod HP Omen (7)
2024-03-29, 11:33:05
xx [Poradnik] Wyszukiwanie Sterowników (2)
2024-03-27, 21:08:23
xx Ile pingwinów? (1)
2024-03-27, 08:59:24

Autor Wątek: std::srand  (Przeczytany 2160 razy)

pawel_lok@wp.pl

  • Gość
std::srand
« dnia: 2016-09-08, 13:42:19 »
Witam,
mam problem z rand(), funkcja bardzo często zwraca mi te same wartości, moim zdaniem nie powinno tak być. Program poprawnie zapisuje liczby od 1 do 80 w tablicy. rand() % x - zwraca losową liczbe z zakresu od zera do x jak rozumiem. Wylosowana liczba trafia na koniec a kocowa liczba jest zapisywana w miejsce wylosowanej, jakim cudem program mi zwraca czasem te same liczby ?

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int losowanie( int min, int max )
{
//   srand( time( 0 ) );
std::srand(std::time(0));
  return( rand() % max ) + min;
}



int main()
{
  int liczba[ 100 ];
    int licznik = 10;
    int lin = 0;
    int los = 0;
    int mt = 89;
    int pom = 0;
    int pom2 = 0 ;
    do
    {
      liczba[ licznik  ] = licznik -9 ;
      licznik++;
    } while( licznik < 90 );


do
{


   do
   {
   int dd = losowanie( 10, mt    );
   cout << liczba[ dd ] << ", ";
   lin++;

   pom = liczba[dd];
   pom2 = liczba[mt];
   liczba[mt] = pom;
   liczba[dd] = pom2;

mt--;
     
  } while( lin < 10 );
   
   std::cout << std::endl ;
   los++;
   lin = 0 ;
} while ( los < 8 );
   

   
    return 0;

« Ostatnia zmiana: 2016-09-09, 07:50:23 wysłana przez Paweł Kraszewski »

Offline vanhelzing

  • Users
  • Prawie jak Guru
  • ****
  • Wiadomości: 314
    • Zobacz profil
Odp: std::srand
« Odpowiedź #1 dnia: 2016-09-08, 15:37:10 »
srand w funkcji losowanie resetuje Ci ciąg pseudolosowy przy każdym losowaniu. Jeżeli np. wywołasz ciąg instrukcji:
srand(0);
rand()
zawsze dostaniesz tą samą liczbę jako wynik "rand".
"time()" ma rozdzielczość 1s, więc wartość zwracana przez funkcję "losowanie" będzie się zmieniać co sekundę.
Wyrzuć srand(time()) z funkcji losującej i umieść na początku main, tylko podczas inicjalizacji. Najlepiej użyj jako seed funkcji z większą rozdzielczością, np clock() albo czas w milisekundach.

Offline Paweł Mir

  • Users
  • Nowy na forum
  • *
  • Wiadomości: 31
    • Zobacz profil
Odp: std::srand
« Odpowiedź #2 dnia: 2016-09-08, 18:01:10 »
Cytuj
Najlepiej użyj jako seed funkcji z większą rozdzielczością, np clock() albo czas w milisekundach.

nie mogę znaleźć jak tego użyć

do kodu dodalem
#include <unistd.h>

a funkcja sleep i usleep po prostu nie działa (bralem parametr jako sekundy i mili sec)

nie mam pojęcia jak to ugryź, podpowie ktoś ?jest to mój pierwszy program po 10 latach 

to nie jest żadne zaliczenie :)
« Ostatnia zmiana: 2016-09-08, 18:04:33 wysłana przez Paweł Mir »

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3056
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Odp: std::srand
« Odpowiedź #3 dnia: 2016-09-09, 08:09:58 »
a funkcja sleep i usleep po prostu nie działa (bralem parametr jako sekundy i mili sec)

Ale co ma (u)sleep do wypowiedzi kol. vanhelzinga?

Reinicjalizujesz generator przy każdym odczycie. Przy PRNG to poważny błąd, bo przy takim użyciu zwracana liczba to deterministyczna funkcja czasu. Należy to robić RAZ na początku działania programu.

Teraz przerysowuję:
PRNG (czyli m.in srand i seed) działają tak:

seed - ustawia kostkę na stole w konkretnej pozycji.
srand - bierze kostkę, obraca ją w konkretny (jednoznaczny i zawsze ten sam) sposób, odkłada na stół i zwraca jako wynik to, co jest na wierzchu.

Wiec tak:
1. masz kostkę ze ściankami numerowanymi 0..5
2. przed każdym losowaniem ustawiasz seed-em kostkę na pozycji takiej, że wartość na górze kostki to ile dziesiątek minut wyświetla Twój zegarek. (jak jest 8:15 to ustawiasz kostkę 1-ą do góry), zaś na ściankach bocznych - ścianka z największą wartością jest skierowana do ciebie.
3. robisz zawsze to samo przekształcenie kostki srand-em (np przewracasz raz do przodu, raz w lewo, obracasz o 90 stopni zgodnie ze wskazówkami zegara i obracasz raz do siebie)
4. Zapisujesz na kartce wynik "losowania"
5. wracasz do punktu 2

i jesteś zaskoczony,  że przez 10 minut dostajesz cały czas ten sam wynik.
« Ostatnia zmiana: 2016-09-09, 08:13:15 wysłana przez Paweł Kraszewski »
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

pawel_lok@wp.pl

  • Gość
Odp: std::srand
« Odpowiedź #4 dnia: 2016-09-09, 15:03:08 »
srand( time( 0 ) ); umieściłem w main, tak miałem na samym początku, później  dopiero dodałem to do funkcji losowanie,

poradziłem sobie w taki sposób , że 2 liczby z zakresu 1-80 i zamieniam wartości miejscami i tak 1000000, w efekcie mam to czego chcialem

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3056
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Odp: std::srand
« Odpowiedź #5 dnia: 2016-09-09, 16:43:14 »
A jak już przy tym jesteśmy, co jest nie tak z std::shuffle?
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy

Offline Paweł Mir

  • Users
  • Nowy na forum
  • *
  • Wiadomości: 31
    • Zobacz profil
Odp: std::srand
« Odpowiedź #6 dnia: 2016-09-09, 20:08:37 »
Panie Pawle, z std::shuffle jest tak ze o tym po prostu  nie wiedziałem, nie zajmuję programowaniem . Dziękuje za pomoc, dzieki Tobie  , kod ma o wiele linijek mniej ,  i dziala super :)


p.s.
na razie mam w btc 1,60 zl w przeliczniku, jak bedzie na piwo dobre to dokona sie transfer :)

Offline Paweł Kraszewski

  • Administrator
  • Guru
  • *****
  • Wiadomości: 3056
  • Lenistwo jest matką potrzeby = babcią wynalazku
    • Zobacz profil
Odp: std::srand
« Odpowiedź #7 dnia: 2016-09-09, 21:02:45 »
Z mojej strony polecam lekturę C++ Reference, zwłaszcza działy "algorithms", "containers", "numeric" i "utilities".

Przepraszam za język, ale jak ja programuję i napotykam jakiś problem, to pierwsze pytanie jest takie: "Czy jestem tak zaj*bisty, że pierwszy na świecie mam ten problem?". Odpowiedź na ogół jest "nie" i wiele problemów jest rozwiązanych już na poziomie biblioteki standardowej albo podstawowych bibliotek dodatkowych (przede wszystkim Boost). Dodatkowo C++11/14/17 ma wiele fajnych rozwiązań ułatwiających życie.

Kiedyś "oficjalna" iteracja bo wektorze wyglądała tak:
std::vector<int> numbers;
numbers.push(1);
numbers.push(2);
numbers.push(3);
numbers.push(4);
numbers.push(5);
numbers.push(6);
numbers.push(7);
for ( std::vector<int>::iterator ii = numbers.begin();
          ii != numbers.end();
          ii++ )
{
   std::cout<< *ii <<std::endl;
}

Teraz tak:
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto ii : numbers)
{
   std::cout<< ii <<std::endl;
}

Generalnie nowe standardy C++ dają nowe, fajne możliwości.
« Ostatnia zmiana: 2016-09-09, 21:12:12 wysłana przez Paweł Kraszewski »
Paweł Kraszewski
~Arch/Void/Gentoo/FreeBSD/OpenBSD/Specjalizowane customy