Я знаю, что этот пост старый, но предлагаемые ответы не создают единые беспристрастные случайные числа. Принятый ответ по существу это:
% echo $(($(tr -cd 0-9 </dev/urandom | head -c 3) % 60))
Проблема с этим предложением в том, что при выборе 3-значное число от /dev/urandom
, диапазон 0-999, в общей сложности 1000 номеров. Однако 1000 не делятся на 60 равномерно. Таким образом, вы будете склонны к созданию 0-959 чуть более 960-999.
Второго ответ, в то время как творческий подход в использовании наносекунд от ваших часов, страдает от того же предвзятого подхода:
% echo $(($(date +%N) % 60))
Диапазона наносекунд 0-999,999,999, что на 1 млрд номеров. Итак, если вы разделите этот результат на 60, вы снова будете смещены в сторону создания 0-999,999,959 немного больше, чем 999,999,960-999,999,999.
Все остальные ответы являются одинаково предвзятыми неравномерными поколениями.
Чтобы создать непредвзятые однородные случайные числа в диапазоне 0-59 (это то, что я предполагаю, что он означает, а не 0-60, если он пытается рандомизировать запись crontab(1)
), нам нужно заставить результат быть множественным 60.
Во-первых, мы будем генерировать случайные 32-разрядное число в диапазоне от 0 и 4294967295:
% RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')
Теперь мы заставим наш диапазон составляет от $ MIN и 4294967295, что является кратным 60:
% MIN=$((2**32 % 60)) # 16
Это означает:
4294967296 - 16 = 4294967280
4294967280/60 = 71582788.0
Другими словами, мой диапазон [16, 4294967295] точно кратны 60. Таким образом, каждый номер я произвожу в этом диапазоне, а затем разделить на 60, будет в равной степени вероятно, как любое другое число. Таким образом, у меня есть несмещенный генератор чисел 0-59 (или 1-60, если вы добавите 1).
Единственное, что осталось сделать, это убедиться, что мой номер от 16 до 4294967295. Если мое число меньше 16, то мне нужно создать новый номер:
% while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
% MINUTE=$(($RNUM % 60))
Все, что положить вместе для копирования/вставки goodnees:
#!/bin/bash
RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')
MIN=$((2**32 % 60))
while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
MINUTE=$(($RNUM % 60))
Мне это нравится! – Adrian
Ах. Я прочитал вопрос таким образом, чтобы убедиться, что/dev/urandom нет. Это отличное решение. – Thedward
Я получаю 'tr: незаконная последовательность байтов' –