2012-12-18 13 views
5

Pracuję w C i próbuję (rozpaczliwie) zrobić losowy generator, który nie tylko generuje inny numer za każdym razem, gdy uruchamiam generator, ale także inną sekwencję za każdym razem, gdy uruchom program. Testowałem prawie wszystko, co znalazłem online. Otrzymałem 2 dobre sposoby na zrobienie dobrego losowego generatora. Pierwszym z nich jest użycie innego materiału siewnego za każdym razem. Ale to oznacza, że ​​muszę użyć innego losowego materiału siewnego za każdym razem, sprawy, której początkowo nie rozwiązałem. Oto, co próbuję teraz, ale to nie jest prawdziwie losowych jak chcę:próbuje znaleźć całkowicie losowy generator liczbowy

int myrand(int random_seed){ 
    random_seed = random_seed * 1103515245 +12345; 
    return (unsigned int)(random_seed/65536) % 32768; 
          } 

każdym razem i wywołania funkcji i zwiększenie ziarno o 1.

Drugim sposobem jest użycie zmiany time.time a to randomness.I próbował również wiele sposobów Aby to zaimplementować. Moja ostatnia próba jest tutaj: Compiler error-Possible IDE error"undefined reference to gettimeofday error" , ale nie mogłem użyć funkcji gettimeofday, ponieważ pracuję w systemie Windows. Również w tym pytaniu nie otrzymałem żadnych odpowiedzi.

Czy ktoś mógłby mi pomóc, w jaki sposób mogę wdrożyć losowy generator (prawdopodobnie używając czasu) w C działający w systemie Windows? Czy powinienem używać Uniksa?

+2

Czy coś złego 'srand()'? Możesz zaszczepić to czas taki jak ten: 'srand (time (NULL));' –

+0

Próbowałem również srand (time (NULL)), ale musiałem zrobić opóźnienia, aby czekać na zmianę czasu. Powodem jest to, że Chcę wygenerować dużą liczbę liczb losowych w jednym i nie chcę czekać 2 minuty na program do ich generowania.Miałem również próbować użyć milisekund, ale bez powodzenia.Może milisekundy jest odpowiedź, ale nie mogłem wdrożyć go poprawnie, znowu problem polegał na tym, że używam Windows. – Dchris

+2

@ Dchris: zapełnij generator liczb pseudolosowych (PRNG) czasem * raz * na początku programu. Wtedy być może będziesz musiał nie uruchamiać swojego programu więcej niż raz na sekundę (i wprowadzenie milisekund pomoże w tym), ale nie musisz czekać jednej sekundy za każdym razem, gdy czytasz numer z PRNG. –

Odpowiedz

4

Zasiej swój RNG dobrym źródłem entropii.

W systemie Unix użyj/dev/random.

pod Windows, użyć czegoś jak CryptoAPI - Windows equivalent of /dev/random

+1

Jest to ważne tylko dla losowości. Odczytywanie z/dev/random spowoduje drenaż systemu entropii, który spowoduje zablokowanie, gdy będzie w końcu pusty, aż system zgromadzi więcej entropii. Oczywiście PO nie stwierdził, czy problem, który próbuje rozwiązać, jest związany z bezpieczeństwem, czy też nie. Podejrzewam, że tak nie jest. –

+0

zmieniono, aby zauważyć, że można po prostu rozstawić rng w ten sposób. –

+1

W C++ 11 można użyć ['std :: random_device'] (http://en.cppreference.com/w/cpp/numeric/random/random_device), które będą prawdopodobnie używać dowolnego źródła prawdziwie losowych danych system. –

3

co prosicie nie jest generator liczb losowych, ale jak korzystać z generatora liczb losowych już zawarte w standardowej bibliotece C.

Wszystko, co musisz zrobić, to nasienie kiedyś przy uruchamianiu programu:

srand(time(NULL)); 

to wszystko. Jest przenośny i da ci inną sekwencję przy każdym uruchomieniu programu, biorąc pod uwagę, że minęło co najmniej jedna sekunda od ostatniego uruchomienia.

Nie ma nic złego w ponownym podłożeniu go później, ale bez sensu.

+0

Nie należy lekceważyć zasiewów. W zależności od algorytmu PRNG może być pożądane ponowne nasadzanie w celu zwiększenia entropii, ale istnieją zdecydowanie dobre i złe metody resekcji i ataki kryptograficzne oparte na słabym reseeding. Jak już powiedziałeś, ponowne użycie zwykłych przypadków użycia PRNG zwykle nie jest konieczne. Na przykład algorytm MT może wygenerować zdumiewające liczby 2^19937-1, zanim się powtórzy. Inne są dobre do 2^32 numerów przed jazdą na rowerze. – bot403

1

Biblioteka standardowa C ma nagłówek time.h (lub ctime, jeśli używasz C++) (reference). Funkcje tam będą obsługiwane w systemach Windows i Unix.

Polecam time() lub clock() jako seed dla generatora liczb losowych.

Innym sposobem, aby uzyskać całkowicie losowy wejście jest użycie pozycji myszy lub innych rzeczy pod wpływem z zewnątrz.

0

Istnieje wiele sposobów implementacji prng, ale niestety żaden z nich nie jest generatorem liczb losowych. czas (NULL) to dobre podejście, ale używam "blum blum shub". Generuje on jedną bitową liczbę losową:

0

Ponieważ wyraźnie pytasz o rozwiązanie dla systemu Windows, sugeruję, aby unikać time(NULL) lub clock() jako materiału siewnego dla srand(), ponieważ ich granulacja jest bardzo ograniczona (ms).Zamiast tego można użyć wynik licznika wydajności:

LARGE_INTEGER PerformanceCount; 
QueryPerformanceCounter(&PerformanceCount); 
srand(PerformanceCount.LowPart); 

Tempo przyrostu częstości QueryPerformanceCounter() można uzyskać przez wywołanie QueryPerformanceFrequency(). Zazwyczaj wzrasta co najmniej o 1 MHz, a czasem nawet w zakresie GHz. Dlatego zapewnia szybko zmieniające się źródło materiału siewnego.

Edit: Jak zrozumiałem z twojej earlier question również gettimeofday() zarówno realizacja nie da drobnej ziarnistości. Może wyświetlać słowo tv_usec w swojej argumentacji, ale w przypadku systemu Windows nie zapewnia mikrosekund granularności, tak jak ma to miejsce w systemach Linux.

0

cytat:

to make a random generator that not only generates a different number every time i run the generator

Definicje losowych nie obejmują tego pojęcia. Raczej chodzi o to, że masz równą szansę na wybranie dowolnej liczby, niezależnie od wcześniej wybranego numeru. Oznacza to, że teoretycznie możliwe jest dwukrotne wybieranie tego samego numeru.

Jeśli masz do czynienia z talią kart, która spełnia twoje kryterium braku duplikatów. Korzystanie z podejścia do ustalania talii oznacza śledzenie "używanych" numerów.

Należy również pamiętać, że PNRG (generator liczb pseudolosowych) są cykliczne (okresowe). Po wygenerowaniu liczb, zwykle dużej liczby, zaczynasz od nowa i powtarzasz dokładnie sekwencję numerów. Funkcja UNIX rand() generuje liczby całkowite liczby całkowite z zakresu [0, {RAND_MAX}] i ma okres 2^32

naprawdę uważają przeczytaniu tego krótkiego strony:

Patrz: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html