Ответы:
Использование $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
диапазон - 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 в вашей системе, если вы получите истинные или псевдослучайные числа. Истинные случайные числа генерируются с помощью шума, получаемого от драйверов устройств, таких как мышь, жесткий диск, сеть
Вы можете получить случайные числа из файла с дд
Я взял несколько из этих идей и создал функцию, которая должна быстро работать, если требуется много случайных чисел.
звонить 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), когда начальное число не указано, и через random (3), когда задано начальное число.
Основываясь на великолепных ответах @Nelson, @Barun и @Robert, вот скрипт Bash, который генерирует случайные числа.
/dev/urandom
что намного лучше, чем встроенный в Bash$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