Tak.
Random.NextDouble zwraca podwójną wartość między 0 a 1. Następnie mnożysz to przez zakres, do którego chcesz wejść (różnica między maksimum a minimum), a następnie dodajesz to do podstawy (minimum).
public double GetRandomNumber(double minimum, double maximum)
{
Random random = new Random();
return random.NextDouble() * (maximum - minimum) + minimum;
}
Prawdziwy kod powinien mieć losowy element statyczny. Pozwoli to zaoszczędzić koszty tworzenia generatora liczb losowych i umożliwi bardzo częste wywoływanie GetRandomNumber. Ponieważ inicjalizujemy nowy RNG przy każdym wywołaniu, jeśli zadzwonisz wystarczająco szybko, aby czas systemowy nie zmienił się między wywołaniami, RNG zostanie zapełniony dokładnie tym samym znacznikiem czasu i wygeneruje ten sam strumień liczb losowych.
public double GetRandomNumber(this Random random, double minimum, double maximum) {...}
Johnny5 zasugerował utworzenie metody rozszerzającej. Oto pełniejszy przykład kodu pokazujący, jak możesz to zrobić:
Teraz możesz to nazwać tak, jakby to była metoda w
Random
klasie:Zwróć uwagę, że nie powinieneś tworzyć wielu nowych
Random
obiektów w pętli, ponieważ spowoduje to prawdopodobieństwo uzyskania tej samej wartości wiele razy z rzędu. Jeśli potrzebujesz wielu liczb losowych, utwórz jedną instancjęRandom
i wykorzystaj ją ponownie.źródło
Uważaj: jeśli generujesz
random
wewnętrzną pętlę, jak na przykładfor(int i = 0; i < 10; i++)
, nie umieszczajnew Random()
deklaracji wewnątrz pętli.Z MSDN :
Więc opierając się na tym fakcie, zrób coś takiego:
W ten sposób masz gwarancję, że otrzymasz różne podwójne wartości.
źródło
Najprostsze podejście po prostu wygeneruje liczbę losową z przedziału od 0 do różnicy tych dwóch liczb. Następnie dodaj do wyniku mniejszą z dwóch liczb.
źródło
Możesz użyć takiego kodu:
źródło
Możesz to zrobić:
źródło
Trochę spóźniłem się na imprezę, ale musiałem wdrożyć ogólne rozwiązanie i okazało się, że żadne z rozwiązań nie jest w stanie zaspokoić moich potrzeb.
Przyjęte rozwiązanie jest dobre dla małych zasięgów; jednakże
maximum - minimum
może to być nieskończoność dla dużych zakresów. Tak więc poprawioną wersją może być ta wersja:To ładnie generuje liczby losowe, nawet między
double.MinValue
adouble.MaxValue
. Ale to wprowadza kolejny „problem”, który ładnie przedstawiono w tym poście : jeśli użyjemy tak dużych zakresów, wartości mogą wydawać się zbyt „nienaturalne”. Na przykład po wygenerowaniu 10 000 losowych podwójnych wartości z zakresu od 0 dodouble.MaxValue
wszystkich wartości znajdowały się w przedziale od 2,9579E + 304 do 1,7976E + 308.Stworzyłem więc również inną wersję, która generuje liczby w skali logarytmicznej:
Niektóre testy:
Oto posortowane wyniki generowania 10000 losowych liczb podwójnych z przedziału od 0 i
Double.MaxValue
przy obu strategiach. Wyniki wyświetlane są w skali logarytmicznej:Chociaż liniowe wartości losowe wydają się na pierwszy rzut oka błędne, statystyki pokazują, że żadna z nich nie jest „lepsza” od drugiej: nawet strategia liniowa ma równomierny rozkład, a średnia różnica między wartościami jest prawie taka sama w przypadku obu strategii .
Gra z różnymi zakresami pokazała mi, że strategia liniowa staje się „rozsądna” w zakresie od 0
ushort.MaxValue
do „rozsądnej” wartości minimalnej 10,78294704 (dlaulong
zakresu minimalna wartość to 3,03518E + 15int
;: 353341). Oto te same wyniki obu strategii wyświetlane w różnych skalach:Edytować:
Niedawno uczyniłem moje biblioteki open source, zapraszam do obejrzenia
RandomExtensions.NextDouble
metody z pełną walidacją.źródło
A co jeśli jedna z wartości jest ujemna? Nie byłoby lepszym pomysłem:
źródło
Math.Abs()
jest zbędny. Ponieważ zapewniłeś tomin >= max
, i takmax - min
musi to być liczba nieujemna.Jeśli potrzebujesz losowej liczby z zakresu [
double.MinValue
;double.MaxValue
]Użyj zamiast tego:
źródło
Jeśli chodzi o generowanie tej samej liczby losowej, jeśli wywołasz ją w pętli, fajnym rozwiązaniem jest zadeklarowanie nowego obiektu Random () poza pętlą jako zmiennej globalnej.
Zauważ, że musisz zadeklarować swoją instancję klasy Random poza funkcją GetRandomInt, jeśli zamierzasz to uruchomić w pętli.
"Dlaczego to?" ty pytasz.
Cóż, klasa Random w rzeczywistości generuje liczby pseudolosowe, a „ziarnem” randomizera jest czas systemowy. Jeśli twoja pętla jest wystarczająco szybka, zegar systemowy nie będzie się różnił od randomizera, a każda nowa instancja klasy Random będzie rozpoczynać się od tego samego ziarna i dawać tę samą pseudolosową liczbę.
Źródło jest tutaj: http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/
źródło
Użyj statycznego losowania lub liczby mają tendencję do powtarzania się w ciasnych / szybkich pętlach, ponieważ zegar systemowy je rozdziela.
Zobacz też: https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8
źródło
źródło