$RANDOM
是 Bash 中用來(lái)生成 0 至 32767 之間隨機(jī)整數(shù)的一個(gè)內(nèi)置 函數(shù)(而非常量)
其不應(yīng)被用于生成密鑰
樣例-1. 生成隨機(jī)數(shù)
#!/bin/bash
# $RANDOM 每一次調(diào)用都會(huì)返回一個(gè)隨機(jī)的不同的整數(shù)。
# 隨機(jī)數(shù)的標(biāo)稱范圍為 0 - 32767(16位有符號(hào)整型)产捞。
MAXCOUNT=10
count=1
echo
echo "$MAXCOUNT random numbers:"
echo "-----------------"
while [ "$count" -le $MAXCOUNT ] # 生成 10 ($MAXCOUNT) 個(gè)隨機(jī)整數(shù)翰铡。
do
number=$RANDOM
echo $number
let "count += 1" # 增加計(jì)數(shù)掀泳。
done
echo "-----------------"
# 如果你需要一個(gè)小于指定上界的隨機(jī)數(shù)孩饼,可以使用 'modulo' 操作符晶疼。
# 該操作符可以返回除法后的余數(shù)袜蚕。
RANGE=500
echo
number=$RANDOM
let "number %= $RANGE"
# ^^
echo "Random number less than $RANGE --- $number"
echo
# 如果你需要生成的隨機(jī)數(shù)大于一個(gè)指定的下界叽奥,
#+ 可以增加一步判斷俱两,判別并丟棄所有小于下界的數(shù)饱狂。
FLOOR=200
number=0 # 初始化
while [ "$number" -le $FLOOR ]
do
number=$RANDOM
done
echo "Random number greater than $FLOOR --- $number"
echo
# 現(xiàn)在來(lái)看一種可以代替上面循環(huán)的更簡(jiǎn)單的方式,也就是
# let "number = $RANDOM + $FLOOR"
# 該方式可以不使用 while 循環(huán)宪彩,效率更高休讳。
# 但是,該方法可能會(huì)產(chǎn)生一些問(wèn)題尿孔,是什么呢俊柔?
# 通過(guò)結(jié)合上面的兩種方法筹麸,可以獲得一個(gè)特定范圍內(nèi)的隨機(jī)數(shù)。
number=0 # 初始化
while [ "$number" -le $FLOOR ]
do
number=$RANDOM
let "number %= $RANGE" # 將 $number 縮小至 $RANGE 的范圍內(nèi)雏婶。
done
echo "Random number between $FLOOR and $RANGE --- $number"
echo
# 生成二元選擇值物赶,即真(true)或假(false)。
BINARY=2
T=1
number=$RANDOM
let "number %= $BINARY"
# 如果使用 let "number >>= 14" 可以獲得更優(yōu)的隨機(jī)分布
#+ (除了最低位留晚,其余二進(jìn)制位都右移)酵紫。
if [ "$number" -eq $T ]
then
echo "TRUE"
else
echo "FALSE"
fi
echo
# 扔一個(gè)骰子。
SPOTS=6 # 模 6 的余數(shù)范圍為 0 - 5错维。
# 然后加 1 就可以得到期望的范圍 1 - 6奖地。
# 感謝 Paulo Marcel Coelho Aragao 簡(jiǎn)化了代碼。
die1=0
die2=0
# 如果設(shè)置 SPOTS=7 就可以不用加 1 得到值赋焕。這是不是一種更好的方法参歹,為什么?
# 為了保證公平隆判,獨(dú)立的投每一個(gè)骰子犬庇。
let "die1 = $RANDOM % $SPOTS + 1" # 投第一個(gè)骰子。
let "die2 = $RANDOM % $SPOTS + 1" # 投第二個(gè)骰子侨嘀。
# 哪一種運(yùn)算符有更高的優(yōu)先級(jí)臭挽,
#+ 取余(%)還是加法(+)?
let "throw = $die1 + $die2"
echo "Throw of the dice = $throw"
echo
exit 0
樣例-2. 從牌組中隨機(jī)選牌
#!/bin/bash
# pick-card.sh
# 該樣例演示了如何從數(shù)組中隨機(jī)選擇元素飒炎。
# 隨機(jī)選擇任意一張牌埋哟。
Suites="Clubs
Diamonds
Hearts
Spades"
Denominations="2
3
4
5
6
7
8
9
10
Jack
Queen
King
Ace"
# 注意一個(gè)變量占了多行。
suite=($Suites) # 讀入數(shù)組變量郎汪。
denomination=($Denominations)
num_suites=${#suite[*]} # 數(shù)組中的元素?cái)?shù)量赤赊。
num_denominations=${#denomination[*]}
echo -n "${denomination[$((RANDOM%num_denominations))]} of "
echo ${suite[$((RANDOM%num_suites))]}
# $bozo sh pick-cards.sh
# Jack of Clubs
exit 0
樣咧-3. 模擬布朗運(yùn)動(dòng)
#!/bin/bash
# brownian.sh
# ----------------------------------------------------------------
# 該腳本模擬了布朗運(yùn)動(dòng)。
#+ 布朗運(yùn)動(dòng)是指微小粒子受到流體粒子隨機(jī)碰撞煞赢,
#+ 而在流體中做的無(wú)規(guī)則隨機(jī)運(yùn)動(dòng)抛计。
#+ 也就是俗稱的“醉漢走路”。
# 布朗運(yùn)動(dòng)也可以被視作是一個(gè)簡(jiǎn)化的高爾頓板照筑。
#+ 高爾頓板是一個(gè)有著交錯(cuò)排列的釘子的傾斜板子吹截,
#+ 每次可以從中向下滾動(dòng)一堆石子。
#+ 在板子底端是一排槽位凝危,
#+ 石子最后會(huì)落在槽位中波俄。
# 把它想象成一個(gè)簡(jiǎn)單的彈珠游戲就可以了。
# 當(dāng)運(yùn)行這個(gè)腳本之后蛾默,
#+ 你就會(huì)發(fā)現(xiàn)大部分的石子都聚集在中間的槽位里懦铺。
#+ 這與預(yù)期的二項(xiàng)分布相符。
# 作為模擬高爾頓板的程序支鸡,
#+ 腳本忽略了許多參數(shù)冬念,
#+ 例如板子的傾斜角度趁窃、石子滾動(dòng)的摩擦系數(shù)、
#+ 沖擊角度以及釘子的彈性系數(shù)等等急前。
# 忽略的這些參數(shù)能夠在多大程度上影響模擬的精度醒陆?
# -------------------------------------------------------------
PASSES=500 # 粒子作用數(shù) / 石子數(shù)。
ROWS=10 # 碰撞數(shù) / 每一排釘子的數(shù)量裆针。
RANGE=3 # $RANDOM 的輸出范圍為 0 - 2刨摩。
POS=0 # 滾落左側(cè)或是右側(cè)。
RANDOM=$$ # 將腳本的進(jìn)程 ID 作為
#+ 生成隨機(jī)數(shù)的種子据块。
declare -a Slots # 用于儲(chǔ)存落入每一個(gè)槽位的石子數(shù)量码邻。
NUMSLOTS=21 # 底部槽位的數(shù)量。
Initialize_Slots () { # 初始化數(shù)組另假。
for i in $( seq $NUMSLOTS )
do
Slots[$i]=0
done
echo # 在正式模擬開(kāi)始之前先輸出空行。
}
Show_Slots () {
echo; echo
echo -n " "
for i in $( seq $NUMSLOTS ) # 更精致地輸出數(shù)組中的所有元素怕犁。
do
printf "%3d" ${Slots[$i]} # 每個(gè)結(jié)果都占三個(gè)字符的寬度边篮。
done
echo # 槽位:
echo " |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|"
echo " ||"
echo # 需要注意的是,如果任意一個(gè)槽位中石子的數(shù)量超過(guò) 99奏甫,
#+ 將會(huì)打亂整個(gè)程序的顯示效果戈轿。
# 如果只運(yùn)行 500 次通常可以避免這個(gè)問(wèn)題阵子。
}
Move () { # 將一個(gè)單位左移思杯、右移或保持原地不動(dòng)。
Move=$RANDOM # $RANDOM 到底有多隨機(jī)挠进?讓我們看看...
let "Move %= RANGE" # 標(biāo)準(zhǔn)化至范圍 0 - 2色乾。
case "$Move" in
0 ) ;; # 什么也不做,也就是原地不動(dòng)领突。
1 ) ((POS--));; # 左移暖璧。
2 ) ((POS++));; # 右移。
* ) echo -n "Error ";; # 出現(xiàn)異常>(應(yīng)該永遠(yuǎn)不會(huì)發(fā)生)
esac
}
Play () { # 模擬單次運(yùn)行(內(nèi)部循環(huán))澎办。
i=0
while [ "$i" -lt "$ROWS" ] # 每一排釘子經(jīng)過(guò)且僅經(jīng)過(guò)一次石子。
do
Move
((i++));
done
SHIFT=11 # 為什么是 11 而不是 10金砍?
let "POS += $SHIFT" # 將原點(diǎn)移到中間局蚀。
(( Slots[$POS]++ )) # 調(diào)試:echo $POS
# echo -n "$POS "
}
Run () { # 外部循環(huán)。
p=0
while [ "$p" -lt "$PASSES ]
do
Play
(( p++ ))
POS=0 # 重置為 0恕稠。為什么要這么做琅绅?
done
}
# --------------
# main ()
Initialize_Slots
Run
Show_Slots
# --------------
exit $?
# 練習(xí):
# ---------
# 1) 將結(jié)果顯示為一張直方圖,
#+ 或者是一張散點(diǎn)圖谱俭。
# 2) 修改腳本奉件,使用 /dev/urandom 提到 $RANDOM宵蛀。
# 這會(huì)使腳本更加的隨機(jī)化么?
# 3) 當(dāng)每一個(gè)石子落下的時(shí)候县貌,
#+ 嘗試添加一些動(dòng)畫(huà)效果术陶。
Jipe 提供了一些生成指定范圍內(nèi)隨機(jī)數(shù)的方法
# 生成范圍為 6 到 30 的隨機(jī)數(shù)。
rnumber=$((RANDOM%25+6))
# 生成范圍為 6 到 30 的隨機(jī)數(shù)煤痕,
#+ 并且該隨機(jī)數(shù)能被 3 整除梧宫。
rnumber=$(((RANDOM%30/3+1)*3))
# 需要注意這種方法并不是在所有情況下都能起效。
# 會(huì)在 $RANDOM%30 為 0 時(shí)失效摆碉。
# Frank Wang 建議可以換用下面的方法:
rnumber=$(( RANDOM%27/3*3+6 ))
Bill Gradwohl 提出了一種改良后的僅適用于正數(shù)的公式
rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))
Bill 在這還給出了一個(gè)生成指定范圍內(nèi)隨機(jī)數(shù)的通用函數(shù)
樣例-4. 指定范圍隨機(jī)數(shù)
#!/bin/bash
# random-between.sh
# 生成指定范圍內(nèi)的隨機(jī)數(shù)塘匣。
# Anthony Le Clezio 修正了 187 行和 189 行。
randomBetween() {
# 生成一個(gè)范圍在 $min 和 $max 之間巷帝,
#+ 并且能被 $divisibleBy 整除的
#+ 隨機(jī)正數(shù)或負(fù)數(shù)忌卤。
# 返回的隨機(jī)數(shù)遵循合理的隨機(jī)分布。
# Bill Gradwohl - Oct 1, 2003
syntax() {
# 嵌套函數(shù)楞泼。
echo
echo "Syntax: randomBetween [min] [max] [multiple]"
echo
echo -n "Expects up to 3 passed parameters, "
echo "but all are completely optional."
echo "min is the minimum value"
echo "max is the maximum value"
echo -n "multiple specifies that the answer must be "
echo "a multiple of this value."
echo " i.e. answer must be evenly divisible by this number."
echo
echo "If any value is missing, defaults area supplied as: 0 32767 1"
echo -n "Successful completion returns 0, "
echo "unsuccessful completion returns"
echo "function syntax and 1."
echo -n "The answer is returned in the global variable "
echo "randomBetweenAnswer"
echo -n "Negative values for any passed parameter are "
echo "handled correctly."
}
local min=${1:-0}
local max=${2:-32767}
local divisibleBy=${3:-1}
# 考慮到?jīng)]有給函數(shù)傳參的情況驰徊,給變量設(shè)置默認(rèn)值。
local x
local spread
# 確保 divisibleBy 的值為正數(shù)堕阔。
[ ${divisibleBy} -lt 0 ] && divisibleBy=$((0-divisibleBy))
# 合規(guī)校驗(yàn)棍厂。
if [ $# -gt 3 -o ${divisibleBy} -eq 0 -o ${min} -eq ${max} ]; then
syntax
return 1
fi
# 檢查 min 和 max 的值是否顛倒。
if [ ${min} -gt ${max} ]; then
# 交換它們超陆。
x=${min}
min=${max}
max=${x}
fi
# 如果 min 值本身不能被 $divisibleBy 整除牺弹,
#+ 則將其修正到范圍內(nèi)。
if [ $((min/divisibleBy*divisibleBy)) -ne ${min} ]; then
if [ ${min} -lt 0 ]; then
min=$((min/divisibleBy*divisibleBy))
else
min=$((((min/divisibleBy)+1)*divisibleBy))
fi
fi
# 如果 max 值本身不能被 $divisibleBy 整除时呀,
#+ 則將其修正到范圍內(nèi)张漂。
if [ $((max/divisibleBy*divisibleBy)) -ne ${max} ]; then
if [ ${max} -lt 0 ]; then
max=$((((max/divisibleBy)-1)*divisibleBy))
else
max=$((max/divisibleBy*divisibleBy))
fi
fi
# ---------------------------------------------------------------------
# 接下來(lái)開(kāi)始真正的內(nèi)容。
# 需要注意的是退唠,為了得到端點(diǎn)間合理的隨機(jī)分布鹃锈,
#+ 隨機(jī)數(shù)的取值范圍應(yīng)是 0 至 abs(max-min)+divisibleBy,
#+ 而不是簡(jiǎn)單的 abs(max-min)+1瞧预。
# 少量的增長(zhǎng)將會(huì)帶來(lái)端點(diǎn)間
#+ 合理的隨機(jī)分布屎债。
# 將公式修改為使用 abs(max-min)+1 仍然可以得到正確的答案,
#+ 但是獲得的這些隨機(jī)數(shù)的隨機(jī)性是有缺陷的垢油,
#+ 因?yàn)檫@種情況下返回的端點(diǎn)值 ($min 和 $max) 的次數(shù)遠(yuǎn)少于
#+ 使用正確公式時(shí)所返回的次數(shù)盆驹。
# ---------------------------------------------------------------------
spread=$((max-min))
# Omair Eshkenazi 指出在這里沒(méi)有必要進(jìn)行校驗(yàn),
#+ 因?yàn)?max 和 min 的值已經(jīng)被交換了滩愁。
[ ${spread} -lt 0 ] && spread=$((0-spread))
let spread+=divisibleBy
randomBetweenAnswer=$(((RANDOM%spread)/divisibleBy*divisibleBy+min))
return 0
# 但是 Paulo Marcel Coelho Aragao 指出
#+ 當(dāng) $max 和 $min 不能被 $divisibleBy 整除時(shí)躯喇,
#+ 該公式就會(huì)失效。
#
# 他建議替換為下面的公式:
# rnumber = $(((RANDOM%(max-min+1)+min)/divisibleBy*divisibleBy))
}
# 接下來(lái)測(cè)試函數(shù)。
min=-14
max=20
divisibleBy=3
# 循環(huán)執(zhí)行足夠多次數(shù)的函數(shù)廉丽,生成包含這些隨機(jī)數(shù)的數(shù)組倦微,
#+ 然后校驗(yàn)數(shù)組中是否包含了端點(diǎn)范圍內(nèi)的每一個(gè)數(shù)字。
declare -a answer
minimum=${min}
maximum=${max}
if [ $((minimum/divisibleBy*divisibleBy)) -ne ${minimum} ]; then
if [ ${minimum} -lt 0 ]; then
minimum=$((minimum/divisibleBy*divisibleBy))
else
minimum=$((((minimum/divisibleBy)+1)*divisibleBy))
fi
fi
# 如果 max 值本身不能被 $divisibleBy 整除正压,
#+ 則將其修正到范圍內(nèi)欣福。
if [ $((maximum/divisibleBy*divisibleBy)) -ne ${maximum} ]; then
if [ ${maximum} -lt 0 ]; then
maximum=$((((maximum/divisibleBy)-1)*divisibleBy))
else
maximum=$((maximum/divisibleBy*divisibleBy))
fi
fi
# 需要保證數(shù)組的下標(biāo)只能為正數(shù),
#+ 因此這里需要通過(guò)位移來(lái)保證
#+ 結(jié)果為正焦履。
disp=$((0-minimum))
for ((i=${minimum}; i<=${maximum}; i+=divisibleBy)); do
answer[i+disp]=0
done
# 現(xiàn)在開(kāi)始循環(huán)執(zhí)行函數(shù)以獲得大量的隨機(jī)數(shù)拓劝。
loopIt=1000 # 腳本的作者建議使用 100000,
#+ 但是這會(huì)花費(fèi)大量的時(shí)間嘉裤。
for ((i=0; i<${loopIt}; i++)); do
# 注意郑临,我們?cè)谶@里顛倒了 min 和 max 的值,
#+ 為的是校驗(yàn)函數(shù)在這種情況下是否能正常執(zhí)行屑宠。
randomBetween ${max} ${min} ${divisibleBy}
# 如果獲得了非預(yù)期的答案厢洞,則報(bào)錯(cuò)。
[ ${randomBetweenAnswer} -lt ${min} -o ${randomBetweenAnswer} -gt ${max} ] \
&& echo MIN or MAX error - ${randomBetweenAnswer}!
[ $((randomBetweenAnswer%${divisibleBy})) -ne 0 ] \
&& echo DIVISIBLE BY error - ${randomBetweenAnswer}!
# 保存統(tǒng)計(jì)結(jié)果典奉。
answer[randomBetweenAnswer+disp]=$((answer[randomBetweenAnswer+disp]+1))
done
# 校驗(yàn)最終結(jié)果犀变。
for ((i=${minimum}; i<=${maximum}; i+=divisibleBy)); do
[ ${answer[i+disp]} -eq 0 ] \
&& echo "We never got an answer of $i." \
|| echo "${i} occurred ${answer[i+disp]} times."
done
exit 0
那么 $RANDOM
到底有多隨機(jī)?最好的測(cè)試方法就是寫(xiě)一個(gè)腳本跟蹤由 $RANDOM
生成的隨機(jī)數(shù)的分布
接下來(lái)讓我們多投幾次由 $RANDOM
做的骰子
樣例-5. 用 RANDOM 投骰子
#!/bin/bash
# RANDOM 有多隨機(jī)秋柄?
RANDOM=$$ # 用腳本的進(jìn)程 ID 重置隨機(jī)數(shù)生成器種子。
PIPS=6 # 骰子有 6 個(gè)點(diǎn)蠢正。
MAXTHORWS=600 # 如果你沒(méi)有更好消磨時(shí)間的辦法骇笔,就增加這個(gè)值。
# 投骰子的次數(shù)嚣崭。
ones=0 # 必須初始化計(jì)數(shù)器的值為 0笨触,
twos=0 #+ 因?yàn)槲闯跏蓟淖兞康闹禐?null 而非 0。
threes=0
fours=0
fives=0
sixes=0
print_result ()
{
echo
echo "ones = $ones"
echo "twos = $twos"
echo "threes = $threes"
echo "fours = $fours"
echo "fives = $fives"
echo "sixes = $sixes"
echo
}
update_count()
{
case "$1" in
0) ((ones++));; # 因?yàn)轺蛔記](méi)有 0 點(diǎn)雹舀,所以這個(gè)其實(shí)對(duì)應(yīng)的是 1 點(diǎn)芦劣。
1) ((twos++));; # 這個(gè)對(duì)應(yīng) 2 點(diǎn)。
2) ((threes++));; # 以此類(lèi)推说榆。
3) ((fours++));;
4) ((fives++));;
5) ((sixes++));;
esac
}
echo
while [ "$throw" -lt "$MAXTHROWS" ]
do
let "die1 = RANDOM % $PIPS"
update_count $die1
let "throw += 1"
done
print_result
exit $?
# 假設(shè) RANDOM 是真隨機(jī)虚吟,那么計(jì)數(shù)結(jié)果應(yīng)該均勻分布。
# 當(dāng) $MAXTHROWS 的值為 600 時(shí)签财,每一個(gè)計(jì)數(shù)器的值都應(yīng)該在 100 左右串慰,
#+ 上下浮動(dòng)大約 20。
#
# 記住 RANDOM 是一個(gè) ***偽隨機(jī)*** 生成器唱蒸,
#+ 并且也不是其中最優(yōu)秀的那一個(gè)邦鲫。
# 隨機(jī)化是一個(gè)很深?yuàn)W且復(fù)雜的話題。
# 足夠長(zhǎng)的“隨機(jī)”序列可能會(huì)出現(xiàn)一些
#+ 混亂或其他非隨機(jī)化的表現(xiàn)神汹。
# 練習(xí)(簡(jiǎn)單):
# ---------------
# 重寫(xiě)腳本庆捺,修改為投擲硬幣 1000 次古今。
# 顯示為正面 "HEADS" 和背面 "TAILS"。
從上一個(gè)樣例中我們可以發(fā)現(xiàn)滔以,在每次調(diào)用 RANDOM 生成器時(shí)捉腥,最好利用重置生成器種子
在 RANDOM 生成器中使用相同的種子會(huì)生成相同序列的隨機(jī)數(shù)。(與 C 語(yǔ)言中的 random() 函數(shù)的行為一致)
樣例-6. 重置 RANDOM 種子
#!/bin/bash
# seeding-random.sh: 設(shè)置 RANDOM 變量的種子醉者。
# 版本號(hào) 1.1, 發(fā)布日期 09 Feb 2013
MAXCOUNT=25 # 生成隨機(jī)數(shù)的個(gè)數(shù)但狭。
SEED=
random_numbers ()
{
local count=0
local number
while [ "$count" -lt "$MAXCOUNT" ]
do
number=$RANDOM
echo -n "$number "
let "count++"
done
}
echo; echo
SEED=1
RANDOM=$SEED # 設(shè)置變量 RANDOM 會(huì)為隨機(jī)數(shù)生成器設(shè)置種子。
echo "Random seed = $SEED"
random_numbers
RANDOM=$SEED # 同樣的種子 ...
echo; echo "Again, with same random seed ..."
echo "Random seed = $SEED"
random_numbers # ... 生成了同樣的數(shù)字序列撬即。
#
# 在什么情況下重復(fù)一個(gè)隨機(jī)化序列會(huì)有用立磁?
echo; echo
SEED=2
RANDOM=$SEED # 用不同的種子再試一次 ...
echo "Random seed = $SEED"
random_numbers # ... 生成了不同的數(shù)字序列。
echo; echo
# RANDOM=$$ 利用腳本的進(jìn)程 ID 設(shè)置 RANDOM 的種子剥槐。
# 同樣也可以利用 'time' 或是 'date' 命令設(shè)置 RANDOM 的種子唱歧。
# 更花哨一點(diǎn)的 ...
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }'| sed s/^0*//)
# 從 /dev/urandom (系統(tǒng)的偽隨機(jī)設(shè)備文件)中
#+ 獲取偽隨機(jī)輸出,
#+ 然后通過(guò) "od" 轉(zhuǎn)換為可打印八進(jìn)制字符行粒竖,
#+ 然后 "awk" 命令會(huì)檢索出一個(gè)數(shù)字作為種子颅崩,
#+ 最后用 "sed" 命令刪除數(shù)字前面所有的前置 0。
RANDOM=$SEED
echo "Random seed = $SEED"
random_numbers
echo; echo
exit 0
偽設(shè)備文件 /dev/urandom
提供了比 $RANDOM
變量更隨機(jī)化的偽隨機(jī)數(shù)蕊苗。命令 dd if=/dev/urandom of=targetfile bs=1 count=XXX
將會(huì)創(chuàng)建一個(gè)包含均勻分布的偽隨機(jī)數(shù)的文件沿后。但是想要在腳本中將這些隨機(jī)數(shù)賦值給變量需要做一些變通,比如使用命令 od
或者使用管道導(dǎo)入命令 md5sum
當(dāng)然也有其他在腳本中生成偽隨機(jī)數(shù)的方法
比如: Awk 命令就提供了這樣一種非常簡(jiǎn)易的方法
樣例-7. 使用 awk
命令生成偽隨機(jī)數(shù)
#!/bin/bash
# random2.sh: 返回大小在 0 - 1 內(nèi)朽砰,
#+ 精度為小數(shù)點(diǎn)后 6 位的偽隨機(jī)數(shù)尖滚。例如:0.822725
# 使用 awk rand() 函數(shù)。
AWKSCRIPT=' { srand(); print rand() } '
# 傳遞給 awk 的命令或參數(shù)
# 注意 srand() 重置了 awk 的隨機(jī)數(shù)生成種子瞧柔。
echo -n "Random number between 0 and 1 = "
echo | awk "$AWKSCRIPT"
# 如果省略 'echo' 將會(huì)發(fā)生什么漆弄?
exit 0
# 練習(xí):
# ---------
# 1) 使用循環(huán)結(jié)構(gòu),輸出 10 個(gè)不同的隨機(jī)數(shù)造锅。
# (提示:你必須在每次循環(huán)中使用 srand() 函數(shù)重置種子以獲得不同的隨機(jī)數(shù)種子撼唾。
#+ 如果你省略了這一步會(huì)發(fā)生什么?)
# 2) 利用整型乘數(shù)作為隨機(jī)數(shù)的縮放因子哥蔚,
#+ 生成大小在 10 到 100 之間的隨機(jī)數(shù)倒谷。
# 3) 內(nèi)容與練習(xí) #2 相同,只是這次生成隨機(jī)整數(shù)肺素。
同樣恨锚,命令 date
可以用于 生成整型隨機(jī)數(shù)序列
注記
真正的“隨機(jī)性”,就其存在而言倍靡,只存在于一些類(lèi)似放射性衰變這樣還未被完全理解的自然現(xiàn)象中猴伶,計(jì)算機(jī)只能模擬這樣的隨機(jī)性,因此計(jì)算機(jī)生成的“隨機(jī)數(shù)”序列被稱作偽隨機(jī)數(shù)办桨。
計(jì)算機(jī)用于生成偽隨機(jī)數(shù)的種子可以被視作一個(gè)標(biāo)識(shí)標(biāo)簽呢撞。例如: 你可以將用種子 23 生成的隨機(jī)數(shù)序列視作第23號(hào)序列摧阅。
偽隨機(jī)數(shù)序列的一個(gè)屬性是該序列在開(kāi)始重復(fù)之前的周期長(zhǎng)度祝钢,一個(gè)好的偽隨機(jī)數(shù)生成器能夠生成周期非常長(zhǎng)的序列。