回答:
を使用し$RANDOM
ます。多くの場合、単純なシェル演算と組み合わせると便利です。たとえば、1〜10の乱数を生成するには、次のようにします。
$ echo $((1 + RANDOM % 10))
3
実際のジェネレータはvariables.c
、関数内にありますbrand()
。古いバージョンは単純な線形ジェネレータでした。のバージョン4.0は、1985年の論文への引用付きbash
のジェネレーターを使用しています。これは、おそらく疑似乱数の適切なソースであることを意味します。シミュレーションには使用しません(もちろん暗号には使用しません)が、基本的なスクリプトタスクにはおそらく十分です。
あなたが使用できる深刻な乱数を必要とする何かをしている場合、/dev/random
または/dev/urandom
それらが利用可能な場合:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
、8と9は$RANDOM
、ランダムデータの強力なソースであっても、0から7よりも(わずかにではありますが)確率的に測定可能です。
$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
。例えば、1と100の間の5の乱数を生成します:shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
すると、1から10までのすべての数値を取得します。指定した-n 15
場合でも、これらの10個の数値のみが1回だけ取得されます。これは実際にシャッフルするだけで、乱数を生成しません。
awkから乱数を取得することもできます
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
のシードは現在のCPU時間であることに言及する価値があるかもしれません。特定のシードを指定する必要があり、RNGを複製できるようにするsrand(x)
場合x
は、シードはwhereを使用します。また、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}
1または2を与える可能性は67.8%で、1 ${RANDOM:0:2}
桁の数字(1%である必要があります)を与える可能性は0.03%であり、どちらも0を与える可能性は0.003%です。 。これが問題とならないユースケースはまだあります(例:一貫性のない入力)。
0〜9の乱数。
echo $((RANDOM%10))
$RANDOM
0から32767までしかありません。「ランダムな数字は主に1から3の間で、いくつかのウィングがある」と言っているはずです;)
Linuxシステムを使用している場合は、/ dev / randomから乱数を取得できます。 / dev / urandom。十分な乱数が利用できない場合、/ dev / randomがブロックすることに注意してください。ランダム性よりも速度が必要な場合は、/ dev / urandomを使用してください。
これらの「ファイル」は、オペレーティングシステムによって生成された乱数で埋められます。真または疑似乱数を取得するかどうかは、システム上の/ dev / randomの実装に依存します。真の乱数は、マウス、ハードドライブ、ネットワークなどのデバイスドライバーから収集されたノイズを使用して生成されます。
あなたはddでファイルから乱数を得ることができます
私はこれらのアイデアのいくつかを取り入れ、たくさんの乱数が必要な場合にすばやく実行できる関数を作成しました。
od
多数の乱数が必要な場合、呼び出しは高価です。代わりに、それを1回呼び出して、/ dev / urandomからの1024個の乱数を格納します。いつrand
に呼び出され、最後の乱数が返され、スケーリングされます。その後、キャッシュから削除されます。キャッシュが空になると、さらに1024個の乱数が読み取られます。
例:
rand 10; echo $RET
0から9までのRETの乱数を返します。
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ビットの乱数は、0から9までの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、ジョナサンコルベット、アレッサンドロルビニ、グレッグクロアハートマン]
これら2つのファイルは、カーネルのランダム化、特に
void get_random_bytes_arch(void* buf, int nbytes)
これは、そのような機能がハードウェアによって実装されている場合(通常はそうです)、ハードウェアから真にランダムなバイトを描画します。
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つの数値を取得します(1 0 1
)。順次データを印刷することもできます。マニュアルによると、乱数のソースは次のとおりです。
乱数は、シードが指定されていない場合はarc4random(3)を介して取得され、シードが指定されている場合はrandom(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