Zastosowanie $RANDOM. Jest to często przydatne w połączeniu z prostą arytmetyką powłoki. Na przykład, aby wygenerować losową liczbę od 1 do 10 (włącznie):
$ echo $((1+ RANDOM %10))3
Rzeczywisty generator jest włączony variables.c, funkcja brand(). Starsze wersje były prostym generatorem liniowym. Wersja 4.0 bashwykorzystuje generator z cytatem do artykułu z 1985 roku, co prawdopodobnie oznacza, że jest to przyzwoite źródło liczb pseudolosowych. Nie użyłbym jej do symulacji (a już na pewno nie do kryptografii), ale prawdopodobnie jest to wystarczające do podstawowych zadań skryptowych.
Jeśli robisz coś, co wymaga poważnych liczb losowych, możesz ich użyć /dev/randomlub /dev/urandomjeśli są one dostępne:
Uważaj tutaj. Chociaż jest to w porządku w mgnieniu oka, wykonywanie arytmetyki na liczbach losowych może dramatycznie wpłynąć na losowość wyniku. w przypadku $RANDOM % 108 i 9 są mierzalne (choć marginalnie) mniej prawdopodobne niż 0–7, nawet jeśli$RANDOM jest solidnym źródłem danych losowych.
dimo414
3
@ dimo414 Jestem ciekawy „marginalnie”, czy masz źródło, w którym mogę dowiedzieć się więcej na ten temat?
PascalVKooten
58
Modulując losowe dane wejściowe, „ dziurawiacz ” wyniki. Ponieważ $RANDOM„s zakres to 0-32767numery 0- 7map do 3277różnych możliwych wejść, ale 8i 9może być wytwarzany tylko 3276różne sposoby (bo 32768i 32769nie są możliwe). Jest to niewielki problem w przypadku szybkich hacków, ale oznacza, że wynik nie jest jednolicie losowy. Biblioteki losowe, takie jak Java Random, oferują funkcje do prawidłowego zwracania jednolitej liczby losowej w danym zakresie, zamiast po prostu modyfikować liczbę niepodzielną.
dimo414
1
@JFSebastian bardzo prawdziwe - problem z modulo polega na tym, że może on przełamać jednolitość każdego RNG, nie tylko złych PRNG, ale dzięki za wywołanie tego.
dimo414
14
Tylko dla kontekstu podstawowe szufladkowanie dla% 10 oznacza, że prawdopodobieństwo wystąpienia 8 i 9 jest o około 0,03% mniejsze niż 0–7. Jeśli twój skrypt powłoki wymaga dokładniejszych jednolitych liczb losowych niż to, to zdecydowanie użyj bardziej złożonego i odpowiedniego mechanizmu.
$RANDOM to wewnętrzna funkcja Bash (nie stała), która zwraca pseudolosową liczbę całkowitą z zakresu 0 - 32767. Nie należy jej używać do generowania klucza szyfrowania.
@ JinKwon 32767jest 2^16 / 2 - 1górną granicą 16-bitowej liczby całkowitej ze znakiem.
Jeffrey Martinez
@ JinKwon, czy możesz wyjaśnić, dlaczego tak nie jest 2^15 - 1? Jest to równoważne, więc jestem ciekawy, czy brakuje mi jakiegoś kontekstu?
Brett Holman
11
@BrettHolman Myślę, że próbował wskazać „podpisaną” część 16-bitowej liczby całkowitej ze znakiem. 2 ^ 16 wartości, podzielone na pół dla wartości dodatnich i ujemnych.
Jak przechodzisz w Vars jako koniec zakresu? Mam to:shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
dat tutbrus
1
Dodaj $varzamiast końca zakresu, jak poniżej:var=100 && shuf -i 1-${var} -n 1
knipwim
2
Wolę tę opcję, ponieważ łatwo jest wygenerować N liczb losowych -n. Np. Wygeneruj 5 liczb losowych od 1 do 100 :shuf -i 1-100 -n 5
aerijman
O ile rozumiem, liczby nie są losowe. Jeśli określisz shuf -i 1-10 -n 10, otrzymasz wszystkie liczby od 1 do 10 dokładnie jeden. Jeśli określisz -n 15, nadal dostaniesz tylko te 10 liczb dokładnie raz. To tak naprawdę tylko tasowanie, a nie generowanie liczb losowych.
radlan
Aby uzyskać losowe liczby z zamiennikiem: -r
Geoffrey Anderson
36
Wypróbuj to ze swojej powłoki:
$ od -A n -t d -N 1/dev/urandom
Tutaj -t dokreśla, że format wyjściowy powinien być podpisany dziesiętnie; -N 1mówi, aby przeczytać jeden bajt /dev/urandom.
+1 wiesz, na początku myślałem, dlaczego miałbyś chcieć to zrobić w ten sposób, ale tak naprawdę to lubię.
zelanix
1
Dziękujemy za podanie rozwiązania obejmującego siew. Nigdzie nie mogłem go znaleźć!
Zmęczony
2
+1 za wysiew. Warto wspomnieć, że srand()ziarnem jest aktualny czas procesora. Jeśli musisz podać konkretny materiał siewny, aby RNG można było powielić, użyj srand(x)gdzie xto ziarno. Cytując również z podręcznika funkcji numerycznych GNU awk, „różne implementacje awk używają wewnętrznie różnych generatorów liczb losowych”. Rezultatem jest to, że jeśli jesteś zainteresowany generowaniem rozkładu statystycznego, powinieneś spodziewać się niewielkich różnic między poszczególnymi środowiskami uruchomieniowymi na różnych platformach (wszystkie działające awklub gawk).
Cbhihe
18
Jest $ RANDOM. Nie wiem dokładnie, jak to działa. Ale to działa. Do testowania możesz:
$ RANDOM mieści się w zakresie od 0 do 32767. Otrzymasz więcej liczb, które zaczynają się od 1, 2 lub 3, niż 4-9. Jeśli masz problem z niezrównoważoną dystrybucją, będzie to działać dobrze.
jbo5112,
2
@ jbo5112 masz całkowitą rację, a co z wyświetlaniem ostatniej cyfry? echo $ {RANDOM: 0-1} na jedną cyfrę, $ {RANDOM: 0-2} na dwie cyfry ...?
fraff
3
Jeśli użyjesz ostatnich cyfr, będzie to raczej dobre, ale będzie zawierać 0 i 00. Na pojedynczej cyfrze 0–7 pojawi się o 0,03% częściej niż 8–9. Na 2 cyfrach 0-67 pojawi się o 0,3% częściej niż 68-99. Jeśli potrzebujesz tak dobrej dystrybucji liczb losowych, mam nadzieję, że nie używasz bash. Z oryginałem: ${RANDOM:0:1}ma 67,8% szansy na 1 lub 2, ${RANDOM:0:2}ma tylko 0,03% szansy na nadanie jednocyfrowej liczby (powinno wynosić 1%), a obie mają 0,003% szansy na 0 Nadal istnieją przypadki użycia, w których jest to w porządku (np. Niespójne dane wejściowe).
Mój zły, nie przeczytałem poprawnie strony podręcznika. $RANDOMzmienia się tylko z 0 na 32767. Powinien był powiedzieć „Losowa liczba, głównie między 1 a 3, z kilkoma skrzydłowymi”;)
David Newcomb
1
Co? Będzie to nadal od 0 do 9, chociaż prawdopodobieństwo wystąpienia 8 do 9 będzie nieco mniejsze niż od 0 do 7, jak wspomniano w innej odpowiedzi.
kini
6
Jeśli używasz systemu Linux, możesz uzyskać losową liczbę z / dev / random lub / dev / urandom. Bądź ostrożny / dev / random zablokuje się, jeśli nie będzie wystarczającej liczby losowych numerów. Jeśli potrzebujesz prędkości ponad przypadkowością, użyj / dev / urandom.
Te „pliki” zostaną wypełnione losowymi liczbami generowanymi przez system operacyjny. To zależy od implementacji / dev / random w twoim systemie, jeśli otrzymasz prawdziwe lub pseudolosowe liczby. Prawdziwe liczby losowe są generowane za pomocą szumu zebranego ze sterowników urządzeń, takich jak mysz, dysk twardy, sieć.
Wziąłem kilka z tych pomysłów i stworzyłem funkcję, która powinna działać szybko, jeśli wymaganych jest wiele liczb losowych.
dzwonienie odjest drogie, jeśli potrzebujesz wielu losowych numerów. Zamiast tego dzwonię raz i przechowuję 1024 losowe numery z / dev / urandom. Kiedy randjest wywoływany, ostatni losowy numer jest zwracany i skalowany. Następnie jest usuwany z pamięci podręcznej. Gdy pamięć podręczna jest pusta, odczytywane są kolejne 1024 liczby losowe.
Przykład:
rand 10; echo $RET
Zwraca losową liczbę w RET od 0 do 9 włącznie.
declare -ia RANDCACHE
declare -i RET RAWRAND=$(((1<<32)-1))function rand(){# pick a random number from 0 to N-1. Max N is 2^32local-i N=$1
[[ ${#RANDCACHE[*]}-eq 0]]&&{ RANDCACHE=( $(od -An-tu4 -N1024 /dev/urandom));}# refill cache
RET=$(((RANDCACHE[-1]*N+1)/RAWRAND ))# pull last random number and scale
unset RANDCACHE[${#RANDCACHE[*]}-1]# pop read random number};# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.
declare -i c; declare -ia BIN
for(( c=0; c<100000; c++));do
rand 10
BIN[RET]+=1# add to bin to check distributiondonefor(( c=0; c<10; c++));do
printf "%d %d\n" $c ${BIN[c]}done
AKTUALIZACJA: To nie działa tak dobrze dla wszystkich N. Marnuje również losowe bity, jeśli jest używane z małą N. Zauważ, że (w tym przypadku) 32-bitowa liczba losowa ma wystarczającą entropię dla 9 liczb losowych od 0 do 9 (10 * 9 = 1 000 000 000 <= 2 * 32) możemy wyodrębnić wiele liczb losowych z każdej 32 losowej wartości źródłowej.
#!/bin/bash
declare -ia RCACHE
declare -i RET # return value
declare -i ENT=2# keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT # a store for unused entropy - start with 1 bit
declare -i BYTES=4# size of unsigned random bytes returned by od
declare -i BITS=8*BYTES # size of random data returned by od in bits
declare -i CACHE=16# number of random numbers to cache
declare -i MAX=2**BITS # quantum of entropy per cached random number
declare -i c
function rand(){# pick a random number from 0 to 2^BITS-1[[ ${#RCACHE[*]}-eq 0]]&&{ RCACHE=( $(od -An-tu$BYTES -N$CACHE /dev/urandom));}# refill cache - could use /dev/random if CACHE is small
RET=${RCACHE[-1]}# pull last random number and scale
unset RCACHE[${#RCACHE[*]}-1]# pop read random number};function randBetween(){local-i N=$1
[[ ENT -lt N ]]&&{# not enough entropy to supply ln(N)/ln(2) bits
rand; RND=RET # get more random bits
ENT=MAX # reset entropy}
RET=RND%N # random number to return
RND=RND/N # remaining randomness
ENT=ENT/N # remaining entropy};
declare -ia BIN
for(( c=0; c<100000; c++));do
randBetween 10
BIN[RET]+=1donefor c in ${BIN[*]};do
echo $c
done
Próbowałem tego - zajęło 10 sekund 100% procesora, a następnie wydrukowałem 10 liczb, które wcale nie wyglądały losowo.
Carlo Wood,
Teraz pamiętam. Ten kod generuje 100 000 liczb losowych. Umieszcza każdy w „koszu”, aby sprawdzić, jak losowy. Jest 10 pojemników. Liczby te powinny być podobne, jeśli każda liczba losowa od 0 do 9 jest jednakowo prawdopodobna. Jeśli chcesz wydrukować każdy numer, wyślij echo $ RET po randBetween 10.
philcolbourn
od -An -tu4 -N40 /dev/urandomwygeneruje 10 losowych 32-bitowych liczb całkowitych bez znaku oddzielonych spacjami. możesz przechowywać go w tablicy i użyć go później. twój kod wydaje się przesadą.
Ali
@Ali, OP nie określił, że chcą 32-bitowej liczby losowej o dowolnej wielkości. Ja i niektórzy inni zinterpretowaliśmy to pytanie jako zapewniające losową liczbę w zakresie. Moja funkcja rand osiąga ten cel, a także zmniejsza utratę entropii, która, jeśli zostanie wyczerpana, powoduje blokowanie programów. od on / dev / urandom zwraca tylko 2 ^ N bitowe liczby losowe, a OP musiałby wówczas przechowywać wiele wartości w tablicy, kolejno wyodrębniając je z tej tablicy i uzupełniając tę tablicę. Być może możesz zakodować to jako odpowiedź i obsłużyć inne zakresy liczb losowych?
philcolbourn
@philcolbourn, masz rację co do tego, że OP nie określa, jakiego rodzaju liczb losowych chce, i to zwróciło moją uwagę. Ale on tylko zapytał: „Jak wygenerować na liczbę losową w bash?”. Chodzi mi o to, że poprosił tylko o jedną losową liczbę. Chociaż ten krytyk dotyczy również mojego poprzedniego komentarza (generującego 10 liczb losowych).
Ali,
5
Czytanie z plików specjalnych znaków / dev / random lub / dev / urandom jest właściwą drogą.
Urządzenia te zwracają prawdziwie losowe liczby podczas odczytu i mają pomóc aplikacjom w wyborze bezpiecznych kluczy do szyfrowania. Takie liczby losowe są pobierane z puli entropii, która jest generowana przez różne zdarzenia losowe. {LDD3, Jonathan Corbet, Alessandro Rubini i Greg Kroah-Hartman]
Te dwa pliki są w szczególności interfejsem do randomizacji jądra
void get_random_bytes_arch(void* buf, int nbytes)
który pobiera prawdziwie losowe bajty ze sprzętu, jeśli taka funkcja jest realizowana sprzętowo (zwykle jest), lub pobiera z puli entropii (składającej się z czasów między zdarzeniami, takimi jak przerwania myszy i klawiatury oraz inne przerwania zarejestrowane w SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1| od -t d
Działa, ale zapisuje niepotrzebne dane wyjściowe z ddna standardowe wyjście. Poniższe polecenie podaje tylko liczbę całkowitą, której potrzebuję. Mogę nawet uzyskać określoną liczbę losowych bitów według potrzeb, dostosowując maskę bitową podaną dla rozszerzenia arytmetycznego:
Aby uzyskać kryptograficznie bezpieczną liczbę losową, musisz przeczytać z / dev / urandom lub użyć bibliotek Crypt :: Random.
kh
3
Może jestem trochę za późno, ale co jotz generowaniem losowej liczby w zakresie w Bash?
jot -r -p 3101
Generuje to -rliczbę losową ( ) z dokładnością do 3 miejsc po przecinku ( -p). W tym konkretnym przypadku otrzymasz jedną liczbę od 0 do 1 ( 1 0 1). Możesz także wydrukować dane sekwencyjne. Źródłem liczby losowej, zgodnie z instrukcją, jest:
Liczby losowe są uzyskiwane przez arc4random (3), gdy nie podano nasion, i przez losowe (3), gdy podano ziarno.
Odpowiedzi:
Zastosowanie
$RANDOM
. Jest to często przydatne w połączeniu z prostą arytmetyką powłoki. Na przykład, aby wygenerować losową liczbę od 1 do 10 (włącznie):Rzeczywisty generator jest włączony
variables.c
, funkcjabrand()
. Starsze wersje były prostym generatorem liniowym. Wersja 4.0bash
wykorzystuje generator z cytatem do artykułu z 1985 roku, co prawdopodobnie oznacza, że jest to przyzwoite źródło liczb pseudolosowych. Nie użyłbym jej do symulacji (a już na pewno nie do kryptografii), ale prawdopodobnie jest to wystarczające do podstawowych zadań skryptowych.Jeśli robisz coś, co wymaga poważnych liczb losowych, możesz ich użyć
/dev/random
lub/dev/urandom
jeśli są one dostępne:źródło
$RANDOM % 10
8 i 9 są mierzalne (choć marginalnie) mniej prawdopodobne niż 0–7, nawet jeśli$RANDOM
jest solidnym źródłem danych losowych.$RANDOM
„s zakres to0-32767
numery0
-7
map do3277
różnych możliwych wejść, ale8
i9
może być wytwarzany tylko3276
różne sposoby (bo32768
i32769
nie są możliwe). Jest to niewielki problem w przypadku szybkich hacków, ale oznacza, że wynik nie jest jednolicie losowy. Biblioteki losowe, takie jak JavaRandom
, oferują funkcje do prawidłowego zwracania jednolitej liczby losowej w danym zakresie, zamiast po prostu modyfikować liczbę niepodzielną.Proszę zobaczyć
$RANDOM
:źródło
32767
ma jakieś specjalne znaczenie?32767
jest2^16 / 2 - 1
górną granicą 16-bitowej liczby całkowitej ze znakiem.2^15 - 1
? Jest to równoważne, więc jestem ciekawy, czy brakuje mi jakiegoś kontekstu?Możesz także użyć shuf (dostępne w coreutils).
źródło
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
zamiast końca zakresu, jak poniżej:var=100 && shuf -i 1-${var} -n 1
-n
. Np. Wygeneruj 5 liczb losowych od 1 do 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
, otrzymasz wszystkie liczby od 1 do 10 dokładnie jeden. Jeśli określisz-n 15
, nadal dostaniesz tylko te 10 liczb dokładnie raz. To tak naprawdę tylko tasowanie, a nie generowanie liczb losowych.Wypróbuj to ze swojej powłoki:
Tutaj
-t d
określa, że format wyjściowy powinien być podpisany dziesiętnie;-N 1
mówi, aby przeczytać jeden bajt/dev/urandom
.źródło
od -A n -t d -N 1 /dev/urandom |tr -d ' '
możesz także uzyskać losową liczbę z awk
źródło
srand()
ziarnem jest aktualny czas procesora. Jeśli musisz podać konkretny materiał siewny, aby RNG można było powielić, użyjsrand(x)
gdziex
to ziarno. Cytując również z podręcznika funkcji numerycznych GNU awk, „różne implementacje awk używają wewnętrznie różnych generatorów liczb losowych”. Rezultatem jest to, że jeśli jesteś zainteresowany generowaniem rozkładu statystycznego, powinieneś spodziewać się niewielkich różnic między poszczególnymi środowiskami uruchomieniowymi na różnych platformach (wszystkie działająceawk
lubgawk
).Jest $ RANDOM. Nie wiem dokładnie, jak to działa. Ale to działa. Do testowania możesz:
źródło
Podoba mi się ta sztuczka:
...
źródło
${RANDOM:0:1}
ma 67,8% szansy na 1 lub 2,${RANDOM:0:2}
ma tylko 0,03% szansy na nadanie jednocyfrowej liczby (powinno wynosić 1%), a obie mają 0,003% szansy na 0 Nadal istnieją przypadki użycia, w których jest to w porządku (np. Niespójne dane wejściowe).Losowa liczba od 0 do 9 włącznie.
źródło
$RANDOM
zmienia się tylko z 0 na 32767. Powinien był powiedzieć „Losowa liczba, głównie między 1 a 3, z kilkoma skrzydłowymi”;)Jeśli używasz systemu Linux, możesz uzyskać losową liczbę z / dev / random lub / dev / urandom. Bądź ostrożny / dev / random zablokuje się, jeśli nie będzie wystarczającej liczby losowych numerów. Jeśli potrzebujesz prędkości ponad przypadkowością, użyj / dev / urandom.
Te „pliki” zostaną wypełnione losowymi liczbami generowanymi przez system operacyjny. To zależy od implementacji / dev / random w twoim systemie, jeśli otrzymasz prawdziwe lub pseudolosowe liczby. Prawdziwe liczby losowe są generowane za pomocą szumu zebranego ze sterowników urządzeń, takich jak mysz, dysk twardy, sieć.
Możesz pobrać losowe liczby z pliku za pomocą dd
źródło
Wziąłem kilka z tych pomysłów i stworzyłem funkcję, która powinna działać szybko, jeśli wymaganych jest wiele liczb losowych.
dzwonienie
od
jest drogie, jeśli potrzebujesz wielu losowych numerów. Zamiast tego dzwonię raz i przechowuję 1024 losowe numery z / dev / urandom. Kiedyrand
jest wywoływany, ostatni losowy numer jest zwracany i skalowany. Następnie jest usuwany z pamięci podręcznej. Gdy pamięć podręczna jest pusta, odczytywane są kolejne 1024 liczby losowe.Przykład:
Zwraca losową liczbę w RET od 0 do 9 włącznie.
AKTUALIZACJA: To nie działa tak dobrze dla wszystkich N. Marnuje również losowe bity, jeśli jest używane z małą N. Zauważ, że (w tym przypadku) 32-bitowa liczba losowa ma wystarczającą entropię dla 9 liczb losowych od 0 do 9 (10 * 9 = 1 000 000 000 <= 2 * 32) możemy wyodrębnić wiele liczb losowych z każdej 32 losowej wartości źródłowej.
źródło
od -An -tu4 -N40 /dev/urandom
wygeneruje 10 losowych 32-bitowych liczb całkowitych bez znaku oddzielonych spacjami. możesz przechowywać go w tablicy i użyć go później. twój kod wydaje się przesadą.Czytanie z plików specjalnych znaków / dev / random lub / dev / urandom jest właściwą drogą.
Te dwa pliki są w szczególności interfejsem do randomizacji jądra
który pobiera prawdziwie losowe bajty ze sprzętu, jeśli taka funkcja jest realizowana sprzętowo (zwykle jest), lub pobiera z puli entropii (składającej się z czasów między zdarzeniami, takimi jak przerwania myszy i klawiatury oraz inne przerwania zarejestrowane w SA_SAMPLE_RANDOM).
Działa, ale zapisuje niepotrzebne dane wyjściowe z
dd
na standardowe wyjście. Poniższe polecenie podaje tylko liczbę całkowitą, której potrzebuję. Mogę nawet uzyskać określoną liczbę losowych bitów według potrzeb, dostosowując maskę bitową podaną dla rozszerzenia arytmetycznego:źródło
Co powiesz na:
źródło
Może jestem trochę za późno, ale co
jot
z generowaniem losowej liczby w zakresie w Bash?Generuje to
-r
liczbę losową ( ) z dokładnością do 3 miejsc po przecinku (-p
). W tym konkretnym przypadku otrzymasz jedną liczbę od 0 do 1 (1 0 1
). Możesz także wydrukować dane sekwencyjne. Źródłem liczby losowej, zgodnie z instrukcją, jest:źródło
Oparty na świetnych odpowiedziach @Nelson, @Barun i @Robert, oto skrypt Bash, który generuje losowe liczby.
/dev/urandom
czemu jest znacznie lepsza niż wbudowana Bash$RANDOM
źródło
Wygeneruj liczbę losową z zakresu od 0 do n (16-bitowa liczba całkowita ze znakiem). Zestaw wyników w zmiennej $ RAND. Na przykład:
źródło
Losowe rozgałęzienie programu lub tak / nie; 1/0; wyjście prawda / fałsz:
jeśli leniwy zapamiętać 16383:
źródło