Відповіді:
Використовуйте $RANDOM
. Це часто корисно в поєднанні з простою арифметикою оболонки. Наприклад, для генерації випадкового числа між 1 і 10 (включно):
$ echo $((1 + RANDOM % 10))
3
Фактичний генератор знаходиться в variables.c
, функція brand()
. Старіші версії були простим лінійним генератором. У версії 4.0 bash
використовується генератор із цитатами на папір 1985 року, що, імовірно, означає, що це гідне джерело псевдовипадкових чисел. Я б не використовував це для моделювання (і, звичайно, не для криптовалюти), але це, ймовірно, достатньо для основних завдань сценарію.
Якщо ви робите щось, що вимагає серйозних випадкових чисел, ви можете використовувати /dev/random
або /dev/urandom
якщо вони доступні:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
8 і 9 вимірно (хоча і незначно) менш вірогідні, ніж 0-7, навіть якщо $RANDOM
є надійним джерелом випадкових даних.
$RANDOM
діапазон «S є 0-32767
число 0
- 7
карта для 3277
різних можливих входів, але 8
і 9
можуть бути отримані тільки 3276
різними способами (так як 32768
і 32769
неможливо). Це незначна проблема для швидких злому, але означає, що результат неоднаково випадковий. Випадкові бібліотеки, як і Java Random
, пропонують функції правильного повернення уніфікованого випадкового числа в заданому діапазоні, а не просто модифікацію нероздільного числа.
Будь ласка, дивіться $RANDOM
:
$RANDOM
- це внутрішня функція Bash (не константа), яка повертає псевдовипадкове ціле число в діапазоні 0 - 32767. Її не слід використовувати для створення ключа шифрування.
32767
має якесь особливе значення?
32767
- 2^16 / 2 - 1
це верхня межа для підписаного 16-бітного цілого числа.
2^15 - 1
? Це рівнозначно, тому мені просто цікаво, чи є якийсь контекст, якого я пропускаю?
Ви також можете використовувати shuf (доступний в coreutils).
shuf -i 1-100000 -n 1
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
замість кінця діапазону, як це:var=100 && shuf -i 1-${var} -n 1
-n
. Наприклад, генеруйте 5 випадкових чисел між 1 і 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
ви отримаєте всі числа від 1 до 10 точних. Якщо ви вкажете, -n 15
ви все одно отримаєте лише ті 10 номерів рівно один раз. Це насправді лише перетасовування, не генерування випадкових чисел.
Спробуйте це з вашої оболонки:
$ od -A n -t d -N 1 /dev/urandom
Тут -t d
зазначено, що вихідний формат повинен бути підписаний десятковою; -N 1
каже прочитати один байт з /dev/urandom
.
od -A n -t d -N 1 /dev/urandom |tr -d ' '
ви також можете отримати випадкове число від awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
насіння є поточним процесорним часом. Якщо вам потрібно вказати конкретне насіння, щоб RNG можна було дублювати, використовуйте, srand(x)
де x
є насіння. Крім того, цитується з посібника з числових функцій GNU awk, "різні реалізації awk використовують внутрішньо різні генератори випадкових чисел". Підсумок полягає в тому, що якщо ви зацікавлені в генеруванні статистичного розподілу, вам слід очікувати незначних змін, що переходять від однієї версії до другої на різних платформах (все це працює awk
або gawk
).
Є $ RANDOM. Я не знаю точно, як це працює. Але це працює. Для тестування ви можете:
echo $RANDOM
Мені подобається цей трюк:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
має 67,8% шансів дати вам 1 або 2, ${RANDOM:0:2}
лише 0,03% шансу дати вам одноцифрове число (має бути 1%), і обидва мають шанс 0,003% дати вам 0 Ще є випадки використання, коли це нормально (наприклад, несумісне введення).
Випадкове число від 0 до 9 включно.
echo $((RANDOM%10))
$RANDOM
йде лише від 0 до 32767. Це повинно було сказати "Випадкове число здебільшого між 1 і 3, з кількома крилами";)
Якщо ви використовуєте систему Linux, ви можете отримати випадкове число з / dev / random або / dev / urandom. Будьте обережні / dev / random заблокуються, якщо не буде достатньо випадкових чисел. Якщо вам потрібна швидкість над випадковістю, використовуйте / dev / urandom.
Ці "файли" будуть заповнені випадковими числами, згенерованими операційною системою. Це залежить від реалізації / dev / random у вашій системі, якщо ви отримаєте істинні чи псевдо випадкові числа. Справжні випадкові цифри генеруються за допомогою форми шуму, зібраного від драйверів пристроїв, таких як миша, жорсткий диск, мережа.
Ви можете отримати випадкові числа з файлу за допомогою dd
Я взяв кілька таких ідей і зробив функцію, яка повинна виконуватись швидко, якщо потрібно багато випадкових чисел.
дзвінок od
дорогий, якщо вам потрібно багато випадкових номерів. Натомість я називаю це один раз і зберігаю 1024 випадкових числа з / dev / urandom. Коли rand
викликається, останнє випадкове число повертається та масштабується. Потім він видаляється з кешу. Коли кеш порожній, зчитується ще 1024 випадкових числа.
Приклад:
rand 10; echo $RET
Повертає випадкове число в RET від 0 до 9 включно.
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^32
local -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 distribution
done
for (( c=0; c<10; c++ )); do
printf "%d %d\n" $c ${BIN[c]}
done
ОНОВЛЕННЯ: Це працює не так добре для всіх N. Він також витрачає випадкові біти, якщо використовується з малим N. Зауваживши, що (у цьому випадку) 32-бітове випадкове число має достатню ентропію для 9 випадкових чисел між 0 і 9 (10 * 9 = 1 000 000 000 <= 2 * 32), ми можемо отримати кілька випадкових чисел з кожного 32 випадкового значення джерела.
#!/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]+=1
done
for c in ${BIN[*]}; do
echo $c
done
od -An -tu4 -N40 /dev/urandom
буде генерувати 10 випадкових непідписаних 32-бітових цілих чисел, розділених пробілом. ви можете зберігати його в масиві та використовувати його згодом. ваш код здається надмірним.
Читання спеціальних файлів символів / dev / random або / dev / urandom - це шлях.
Ці пристрої повертають справді випадкові номери під час читання, і вони розроблені, щоб допомогти програмному забезпеченню вибрати безпечні ключі для шифрування. Такі випадкові числа витягуються з пулу ентропії, який сприяють різні випадкові події. {LDD3, Джонатан Корбет, Алессандро Рубіні та Грег Кроа-Хартман]
Ці два файли, зокрема, є інтерфейсом до рандомізації ядра
void get_random_bytes_arch(void* buf, int nbytes)
який малює справді випадкові байти з апаратних засобів, якщо така функція виконується апаратним шляхом (як правило, є), або вона черпає з пулу ентропії (що складається з таймінгів між подіями, такими як перерви миші та клавіатури та інші переривання, зареєстровані SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Це працює, але записує непотрібний вихід з dd
в stdout. Команда нижче дає лише ціле число, яке мені потрібно. Я навіть можу отримати вказану кількість випадкових бітів, як мені потрібно, коригуючи бітову маску, задану для арифметичного розширення:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Можливо, я трохи пізно, але що робити з використанням jot
генерувати випадкове число в межах діапазону в Bash?
jot -r -p 3 1 0 1
Це генерує випадкове ( -r
) число з точністю до 3 знаків після коми ( -p
). У цьому конкретному випадку ви отримаєте одне число від 0 до 1 ( 1 0 1
). Ви також можете друкувати послідовні дані. Джерелом випадкового числа, згідно з посібником, є:
Випадкові числа отримують через arc4random (3), коли не вказано насіння, і через випадкове (3), коли дається насіння.
На основі чудових відповідей @Nelson, @Barun та @Robert, ось сценарій Bash, який генерує випадкові числа.
/dev/urandom
що набагато краще, ніж вбудована Баша$RANDOM
#!/usr/bin/env bash
digits=10
rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
num="${num}$((rand % 10))"
done
echo $num
Створити випадкове число в діапазоні від 0 до n (підписане 16-бітове ціле число). Результат встановлений у змінній $ RAND. Наприклад:
#!/bin/bash
random()
{
local range=${1:-1}
RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
let "RAND=$RAND%($range+1)"
}
n=10
while [ $(( n -=1 )) -ge "0" ]; do
random 500
echo "$RAND"
done
Випадкове розгалуження програми або так / ні; 1/0; істинний / хибний вихід:
if [ $RANDOM -gt 16383 ]; then # 16383 = 32767/2
echo var=true/1/yes/go_hither
else
echo var=false/0/no/go_thither
fi
якщо вам лінь згадати 16383:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi