Jak wygenerować losową liczbę całkowitą w C #?
1918
Random
Klasa służy do tworzenia liczb losowych. (To oczywiście pseudolosowe).
Przykład:
Random rnd = new Random();
int month = rnd.Next(1, 13); // creates a number between 1 and 12
int dice = rnd.Next(1, 7); // creates a number between 1 and 6
int card = rnd.Next(52); // creates a number between 0 and 51
Jeśli zamierzasz utworzyć więcej niż jedną liczbę losową, powinieneś zachować Random
instancję i użyć jej ponownie. Jeśli utworzysz nowe wystąpienia zbyt blisko siebie, wygenerują one tę samą serię liczb losowych, jak generator losowy jest wysyłany z zegara systemowego.
rnd
jakostatic
i / lub ustawić go tylko raz podczas inicjalizacji kodu.Random
...Random
, dzięki którym twoja losowość jest bardziej niezawodna: ericlippert.com/2019/02/04/fixing-random-part-2 i codeblog.jonskeet.uk/2009/11/04/revisiting losowość .Pytanie wygląda na bardzo proste, ale odpowiedź jest nieco skomplikowana. Jeśli widzisz, prawie wszyscy sugerowali użycie klasy Random, a niektórzy sugerowali użycie klasy kryptograficznej RNG. Ale kiedy wybrać, co.
W tym celu musimy najpierw zrozumieć termin RANDOMNESS i leżącą u jego podstaw filozofię.
Zachęcam do obejrzenia tego filmu, który wnika głęboko w filozofię RANDOMNESS przy użyciu C # https://www.youtube.com/watch?v=tCYxc-2-3fY
Po pierwsze, zrozummy filozofię RANDOMNESS. Gdy mówimy osobie, aby wybierała między CZERWONYM, ZIELONYM i ŻÓŁTYM, co dzieje się wewnętrznie. Co sprawia, że dana osoba wybiera CZERWONY, ŻÓŁTY lub ZIELONY?
Pewna wstępna myśl przychodzi do głowy osoby, która decyduje o jego wyborze, może to być ulubiony kolor, szczęśliwy kolor i tak dalej. Innymi słowy, jakiś początkowy wyzwalacz, który określamy w LOSOWO jako SEED. To SEED jest punktem początkowym, wyzwalaczem, który skłania go do wybrania wartości LOSOWANEJ.
Teraz, jeśli SEED jest łatwy do odgadnięcia, wówczas tego rodzaju liczby losowe są określane jako PSEUDO, a gdy nasiona są trudne do odgadnięcia, te liczby losowe są określane jako BEZPIECZNE liczby losowe.
Na przykład osoba wybiera kolor w zależności od pogody i kombinacji dźwięków, wtedy trudno odgadnąć początkowe ziarno.
A teraz pozwólcie, że złożę ważne oświadczenie:
* Klasa „Random” generuje tylko losową liczbę PSEUDO i aby wygenerować BEZPIECZNĄ liczbę losową, musimy użyć klasy „RNGCryptoServiceProvider”.
Klasa losowa pobiera wartości początkowe z zegara procesora, co jest bardzo przewidywalne. Innymi słowy, klasa RANDOM języka C # generuje pseudolosowe liczby, poniżej znajduje się kod tego samego.
** Uwaga: **
.NET Core 2.0.0+
używa innego ziarna w konstruktorze bez parametrów: używa zegara procesoraGuid.NewGuid().GetHashCode()
.Podczas gdy
RNGCryptoServiceProvider
klasa używa entropii systemu operacyjnego do generowania nasion. Entropia systemu operacyjnego jest wartością losową, która jest generowana przy użyciu dźwięku, kliknięcia myszą i ustawień klawiatury, temperatury termicznej itp. Poniżej podano kod dla tego samego.Aby zrozumieć entropię systemu operacyjnego, zobacz ten film od 14:30 https://www.youtube.com/watch?v=tCYxc-2-3fY, gdzie wyjaśniono logikę entropii systemu operacyjnego. Tak więc, mówiąc prosto, RNG Crypto generuje BEZPIECZNE losowe liczby.
źródło
RandomNumberGenerator.Create()
zamiast wywoływania konstruktora,RNGCryptoServiceProvider
ponieważ nie jest on dostępny na wszystkich platformach.Za każdym razem, gdy robisz nowy Random (), jest on inicjowany. Oznacza to, że w ciasnej pętli dostajesz tę samą wartość wiele razy. Powinieneś zachować pojedyncze Losowe wystąpienie i dalej używać Dalej w tym samym wystąpieniu.
źródło
Random
obiekt. W obu przypadkach mam ten sam losowy numer. Przy podejściu Pankaja tak się nie stało. Być może jest to przypadkowe , ale teraz wątpię. Pytam o liczbę losową w tej samej sekundzie z różnych wątków.Uważaj, który
new Random()
jest rozsiewany według bieżącego znacznika czasu.Jeśli chcesz wygenerować tylko jeden numer , możesz użyć:
new Random().Next( int.MinValue, int.MaxValue )
Aby uzyskać więcej informacji, spójrz na klasę Random , ale pamiętaj:
Dlatego nie używaj tego kodu do generowania serii liczb losowych.
źródło
new Random()
w pętli jest ważnym punktem.źródło
Chciałem dodać bezpieczną kryptograficznie wersję:
Klasa RNGCryptoServiceProvider ( MSDN lub dotnetperls )
Implementuje IDisposable.
źródło
Możesz użyć metody StaticRandom Jona Skeeta w bibliotece klas MiscUtil, którą zbudował dla pseudolosowej liczby.
źródło
Wypróbowałem wszystkie te rozwiązania z wyjątkiem odpowiedzi COBOL ... lol
Żadne z tych rozwiązań nie było wystarczająco dobre. Potrzebowałem liczb losowych w szybkiej pętli int i dostawałem mnóstwo zduplikowanych wartości nawet w bardzo szerokich zakresach. Po zbyt długim zadowoleniu z losowych wyników postanowiłem ostatecznie rozwiązać ten problem raz na zawsze.
Chodzi o ziarno.
Tworzę losową liczbę całkowitą, parsując nie-cyfry z Guida, a następnie używam jej do utworzenia mojej losowej klasy.
Aktualizacja : Seeding nie jest konieczny, jeśli raz utworzysz klasę Random. Dlatego najlepiej byłoby stworzyć klasę statyczną i wywołać z niej metodę.
Następnie możesz użyć klasy statycznej w taki sposób ...
Przyznaję, że podoba mi się to podejście.
źródło
Liczby generowane przez wbudowaną
Random
klasę (System.Random) generują pseudolosowe liczby.Jeśli chcesz prawdziwych liczb losowych, najbliższym rozwiązaniem jest „bezpieczny Pseudo losowy generator”, który można wygenerować za pomocą klas kryptograficznych w języku C #, takich jak
RNGCryptoServiceProvider
.Mimo to, jeśli nadal potrzebujesz prawdziwych liczb losowych, będziesz musiał użyć zewnętrznego źródła, takiego jak urządzenia odpowiedzialne za rozpad radioaktywny, jako zalążek generatora liczb losowych. Ponieważ z definicji dowolna liczba wygenerowana za pomocą metod czysto algorytmicznych nie może być prawdziwie losowa.
źródło
utwórz obiekt losowy
i użyj go
nie musisz inicjować za
new Random()
każdym razem, gdy potrzebujesz losowej liczby, zainicjuj jedną Losowo, a następnie użyj jej tyle razy, ile potrzebujesz w pętli lub cokolwiek innegoźródło
new Random()
używa bieżących kleszczy jako nasion. Kiedy utworzysz wiele instancji w ciągu tej samej milisekundy (w przeciwieństwie do tyknięcia), otrzymasz taką samą wartość.Zmodyfikowana odpowiedź stąd .
Jeśli masz dostęp do procesora zgodnego z Intel Secure Key, możesz generować prawdziwe losowe liczby i ciągi znaków za pomocą tych bibliotek: https://github.com/JebteK/RdRand i https://www.rdrand.com/
Wystarczy pobrać najnowszą wersję stąd , dołącz Jebtek.RdRand i dodaj dla niej instrukcję using. Następnie wszystko, co musisz zrobić, to:
Jeśli nie masz zgodnego procesora do wykonania kodu, skorzystaj z usług RESTful na stronie rdrand.com. Z biblioteką otoki RdRandom zawartą w projekcie, wystarczy to zrobić (otrzymasz 1000 darmowych połączeń podczas rejestracji):
źródło
Użyłem poniższego kodu, aby mieć losową liczbę (niezalecane):
źródło
Chociaż jest to w porządku:
Chcesz kontrolować limit (min. I maks. Mumbers) przez większość czasu. Musisz więc określić, gdzie zaczyna się i kończy losowa liczba.
Next()
Sposób dwa parametry, wartości minimalne i maksymalne.Więc jeśli chcę, aby mój losowy numer wynosił między 5 a 15, po prostu bym to zrobił
źródło
Z tej klasy korzystam. Działa jak
RandomNumber.GenerateRandom(1, 666)
źródło
Chciałem pokazać, co się dzieje, gdy za każdym razem używany jest nowy generator losowy. Załóżmy, że masz dwie metody lub dwie klasy, z których każda wymaga losowej liczby. I naiwnie kodujesz je w następujący sposób:
Myślisz, że dostaniesz dwa różne identyfikatory? NIE
Rozwiązaniem jest zawsze stosowanie pojedynczego statycznego generatora losowego. Lubię to:
źródło
RNGCryptoServiceProvider
i tak lepiej zadzwonić.W przypadku silnych losowych nasion zawsze używam CryptoRNG, a nie Time.
źródło
źródło
Tak jak notatka do wykorzystania w przyszłości.
Jeśli używasz platformy .NET Core, wiele przypadkowych wystąpień nie jest tak niebezpiecznych, jak wcześniej. Wiem, że to pytanie pochodzi z 2010 roku, ale ponieważ jest ono stare, ale ma pewną atrakcję, myślę, że dobrze jest udokumentować zmianę.
Możesz odnieść się do pytania, które zadałem:
Czy Microsoft zmienił domyślny domyślny seed?
Zasadniczo zmienili domyślny materiał siewny z
Environment.TickCount
naGuid.NewGuid().GetHashCode()
, więc jeśli utworzysz 2 instancje Losowo, nie będą wyświetlać tych samych liczb.Różnice między plikami z .NET Framework / .NET Core (2.0.0+) można zobaczyć tutaj: https://github.com/dotnet/coreclr/pull/2192/commits/9f6a0b675e5ac0065a268554de49162c539ff66d
Nie jest tak bezpieczny jak RNGCryptoServiceProvider, ale przynajmniej nie da ci dziwnych rezultatów.
źródło
Interop.GetRandomBytes((byte*)&result, sizeof(int));
.Liczby obliczone przez komputer w procesie deterministycznym nie mogą z definicji być losowe.
Jeśli chcesz prawdziwych liczb losowych, losowość pochodzi z hałasu atmosferycznego lub rozpadu radioaktywnego.
Możesz spróbować na przykład RANDOM.ORG (zmniejsza wydajność)
źródło
Umieść dowolne wartości w drugim nawiasie, upewnij się, że ustawiłeś nazwę, pisząc prop i podwójną tabulator, aby wygenerować kod
źródło
Jeśli chcesz, aby CSRNG generował losowe liczby od min. Do maks., Jest to dla Ciebie. Zainicjuje
Random
klasy za pomocą bezpiecznych losowych nasion.źródło
Niestety, OP rzeczywiście wymaga
int
wartości losowej , ale dla prostego celu dzielenia się wiedzą, jeśli chcesz miećBigInteger
wartość losową , możesz użyć następującej instrukcji:źródło
Zakładam, że chcesz równomiernie rozłożonego generatora liczb losowych, jak poniżej. Losowa liczba w większości języków programowania, w tym C # i C ++, nie jest poprawnie tasowana przed użyciem. Oznacza to, że będziesz otrzymywać tę samą liczbę w kółko, co nie jest tak naprawdę losowe. Aby uniknąć ciągłego rysowania tej samej liczby, potrzebujesz ziarna. Zazwyczaj kleszcze w czasie są odpowiednie do tego zadania. Pamiętaj, że będziesz otrzymywał ten sam numer w kółko, jeśli używasz tego samego ziarna za każdym razem. Staraj się więc zawsze używać różnych nasion. Czas jest dobrym źródłem dla nasion, ponieważ zawsze się odradzają.
jeśli szukasz generatora liczb losowych do rozkładu normalnego, możesz użyć transformacji Boxa-Mullera. Sprawdź odpowiedź yoyoyoyosef w Losowym pytaniu zmiennym gaussowskim. Ponieważ chcesz liczbę całkowitą, musisz rzucić podwójną wartość na liczbę całkowitą na końcu.
Losowe zmienne gaussowskie
źródło
Najprostszym sposobem jest prawdopodobnie tylko
Random.range(1, 3)
To wygenerowałoby liczbę od 1 do 2.źródło
Możesz spróbować z losową wartością nasion, używając poniżej:
źródło
Dlaczego nie użyć
int randomNumber = Random.Range(start_range, end_range)
?źródło
Używaj wielokrotnie jednej instancji Losowo
W tym artykule wyjaśniono, dlaczego losowość powoduje tak wiele problemów i jak je rozwiązać. http://csharpindepth.com/Articles/Chapter12/Random.aspx
źródło
Random
nie jest klasą bezpieczną dla wątków. Jeśli utworzysz pojedyncze wystąpienie, powinieneś ograniczyć do niego dostęp za mechanizmem blokującym.Wypróbuj te proste kroki, aby utworzyć losowe liczby:
Utwórz funkcję:
Użyj powyższej funkcji w miejscu, w którym chcesz użyć liczb losowych. Załóżmy, że chcesz go użyć w polu tekstowym.
0 to min, a 999 to max. Możesz zmienić wartości na cokolwiek chcesz.
źródło
Zawsze mam metody generujące liczby losowe, które pomagają w różnych celach. Mam nadzieję, że to też może ci pomóc:
źródło
Szybkie i łatwe do wstawienia, użyj poniżej kodu:
źródło