コマンドをランダムに実行する方法、たとえば10回のうち1回が必要です。これを行うための組み込みまたはGNU coreutilはありますか?理想的には:
chance 10 && do_stuff
do_stuff
10回に1回しか実行されないのはどこですか?スクリプトを記述できることは知っていますが、それはかなり単純なことのように思え、定義された方法があるかどうか疑問に思っていました。
コマンドをランダムに実行する方法、たとえば10回のうち1回が必要です。これを行うための組み込みまたはGNU coreutilはありますか?理想的には:
chance 10 && do_stuff
do_stuff
10回に1回しか実行されないのはどこですか?スクリプトを記述できることは知っていますが、それはかなり単純なことのように思え、定義された方法があるかどうか疑問に思っていました。
回答:
ではksh
、バッシュ、Zshの、ヤシュまたはBusyBoxのsh
:
[ "$RANDOM" -lt 3277 ] && do_stuff
RANDOM
Korn、Bash、Yash、Z、およびBusyBoxシェルの特別な変数は、評価されるたびに0から32767の間の擬似ランダムな10進整数値を生成するため、上記は10分の1のチャンスを(ほぼ)与えます。
これを使用して、少なくともBashでは、質問で説明されているように動作する関数を生成できます。
function chance {
[[ -z $1 || $1 -le 0 ]] && return 1
[[ $RANDOM -lt $((32767 / $1 + 1)) ]]
}
引数を提供するために、忘れる、または無効な引数を提供する、そう、1の結果を生成しますchance && do_stuff
決してdo_stuff
。
これは、「1のための一般的な式を使用して、N」を使用$RANDOM
している、[[ $RANDOM -lt $((32767 / n + 1)) ]]
(⎣32767/与え、N 32768チャンスに⎦+ 1)。値がn
32768の因子ではない場合、可能な値の範囲に不均等な分割があるため、バイアスが発生します。
$((32767/parts+1))
が1を超える制限の差をもたらすか、分割の結果(したがって、制限)が同じであるときにパーツの数が1増加するリスクに直面する必要があります。(続き)
(32767/n-32767/(n+1))>=1
、nを解くと、181.5に制限されます。実際、部品の数は問題なく194個まで実行できました。ただし、195パーツでは、結果の制限は151で、194パーツと同じ結果になります。それは不適合であり、避けるべきです。つまり、部品数(n)の上限は194でなければなりません。制限テストを行うことができます。– [[ -z $1 || $1 -le 1 || $1 -ge 194 ]] && return 1
非標準ソリューション:
[ $(date +%1N) == 1 ] && do_stuff
ナノ秒単位の現在時刻の最後の桁が1であるかどうかを確認してください!
[ $(date +%1N) == 1 ] && do_stuff
が定期的に発生しないことを確認する必要があります。そうしないと、ランダム性が損なわれます。while true; do [ $(date +1%N) == 1 ] && sleep 1; done
抽象的な反例と考えてください。それにもかかわらず、ナノ秒で遊ぶというアイデアは本当に良いです、私はそれを使用すると思うので、+ 1
clock_getres()
)、2)スケジューラは、たとえば、常に100ナノ秒の境界でタイムスライスを開始することを禁止されていません(クロックが正しい場合でもバイアスを導入します)、3)ランダムな値を取得するためのサポートされている方法は、(通常)/dev/urandom
の値の読み取りまたは検査です$RANDOM
。
最初の答えを改善し、達成しようとしていることをより明確にします。
[ $(( $RANDOM % 10 )) == 0 ] && echo "You win" || echo "You lose"
$RANDOM % 10
が$RANDOM
10の異なる値の正確な倍数を生成しない限り、バイアスがあります(通常、バイナリコンピューターでは発生しません)
"$RANDOM" -lt $((32767 / n + 1))
ます。