คำตอบ:
$RANDOM
ใช้ มันมักจะมีประโยชน์เมื่อใช้ร่วมกับการคำนวณทางคณิตศาสตร์อย่างง่าย ตัวอย่างเช่นในการสร้างตัวเลขสุ่มระหว่าง 1 ถึง 10 (รวม)
$ echo $((1 + RANDOM % 10))
3
เครื่องกำเนิดไฟฟ้าที่เกิดขึ้นจริงในฟังก์ชั่นvariables.c
เวอร์ชันที่เก่ากว่าเป็นเครื่องกำเนิดไฟฟ้าเชิงเส้นอย่างง่าย เวอร์ชัน 4.0 ของการใช้เครื่องกำเนิดไฟฟ้าที่มีการอ้างอิงถึงกระดาษ 1985 ซึ่งสันนิษฐานว่าหมายความว่ามันเป็นแหล่งที่ดีของตัวเลขเทียมหลอก ฉันจะไม่ใช้มันสำหรับการจำลอง (และแน่นอนว่าไม่ใช่สำหรับ crypto) แต่มันอาจจะเพียงพอสำหรับงานเขียนสคริปต์ขั้นพื้นฐานbrand()
bash
หากคุณกำลังทำบางสิ่งที่ต้องมีการสุ่มตัวเลขที่รุนแรงคุณสามารถใช้/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
ฉันชอบตัวเลือกนี้เป็นเรื่องง่ายที่จะสร้างตัวเลขสุ่มที่มี N เช่นสร้างหมายเลขสุ่ม 5 หมายเลขระหว่าง 1 ถึง 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
คุณจะได้รับหมายเลขทั้งหมดตั้งแต่ 1 ถึง 10 ที่แน่นอน หากคุณระบุว่า-n 15
คุณจะได้รับเพียง 10 หมายเลขเท่านั้น นั่นคือการสับเท่านั้นไม่สร้างตัวเลขสุ่ม
คุณสามารถรับหมายเลขสุ่มได้จาก awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
เมล็ดของเวลา CPU ปัจจุบัน หากคุณต้องการระบุเมล็ดพันธุ์ที่เฉพาะเจาะจงเพื่อให้สามารถทำซ้ำ 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 กับ wingers ไม่กี่";)
หากคุณใช้ระบบ linux คุณสามารถรับจำนวนสุ่มจาก/ dev / random หรือ / dev / urandom ระวังตัว / dev / สุ่มจะบล็อกหากว่ามีตัวเลขสุ่มไม่เพียงพอ หากคุณต้องการความเร็วมากกว่าการใช้ randomness / dev / urandom
"ไฟล์" เหล่านี้จะถูกเติมด้วยตัวเลขสุ่มที่สร้างโดยระบบปฏิบัติการ ขึ้นอยู่กับการใช้ / dev / random ในระบบของคุณหากคุณได้รับตัวเลขสุ่มจริงหรือหลอก ตัวเลขสุ่มที่แท้จริงจะถูกสร้างขึ้นพร้อมกับเสียงรบกวนในแบบฟอร์มความช่วยเหลือที่รวบรวมจากไดรเวอร์อุปกรณ์เช่นเมาส์ฮาร์ดไดรฟ์เครือข่าย
คุณสามารถรับตัวเลขสุ่มจากไฟล์ด้วยdd
ฉันใช้ความคิดเหล่านี้สองสามข้อและสร้างฟังก์ชันที่ควรทำงานได้อย่างรวดเร็วหากต้องการตัวเลขสุ่มจำนวนมาก
การโทร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
UPDATE: มันใช้ไม่ได้ผลกับ 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
จะสร้างจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อแบบสุ่ม 10 รายการคั่นด้วยช่องว่าง คุณสามารถเก็บไว้ในอาร์เรย์และใช้งานได้ในภายหลัง รหัสของคุณดูเหมือนจะเกินความจริง
การอ่านไฟล์พิเศษจาก / dev / random หรือ / dev / urandom อักขระเป็นวิธีที่จะไป
อุปกรณ์เหล่านี้จะส่งกลับตัวเลขสุ่มอย่างแท้จริงเมื่ออ่านและออกแบบมาเพื่อช่วยให้แอพพลิเคชั่นซอฟต์แวร์เลือกคีย์ความปลอดภัยสำหรับการเข้ารหัส ตัวเลขสุ่มดังกล่าวถูกดึงมาจากเอนโทรปีของสระว่ายน้ำซึ่งมีส่วนร่วมในเหตุการณ์สุ่มต่างๆ {LDD3, Jonathan Corbet, Alessandro Rubini และ Greg Kroah-Hartman]
ไฟล์ทั้งสองนี้เป็นส่วนต่อประสานกับการสุ่มเคอร์เนลโดยเฉพาะ
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 คำสั่งด้านล่างให้จำนวนเต็มที่ฉันต้องการ ฉันยังสามารถรับจำนวนบิตสุ่มที่ระบุตามที่ฉันต้องการโดยการปรับ bitmask ที่กำหนดให้กับการขยายเลขคณิต:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
เกี่ยวกับ:
perl -e 'print int rand 10, "\n"; '
บางทีฉันอาจจะสายไปหน่อย แต่สิ่งที่เกี่ยวกับการใช้jot
เพื่อสร้างตัวเลขสุ่มภายในช่วงใน Bash?
jot -r -p 3 1 0 1
สิ่งนี้จะสร้างตัวเลขสุ่ม ( -r
) ที่มีความแม่นยำทศนิยม 3 ตำแหน่ง ( -p
) ในกรณีนี้คุณจะได้รับหนึ่งหมายเลขระหว่าง 0 ถึง 1 ( 1 0 1
) คุณยังสามารถพิมพ์ข้อมูลตามลำดับ แหล่งที่มาของตัวเลขสุ่มตามคู่มือคือ:
ตัวเลขสุ่มจะได้รับผ่าน arc4random (3) เมื่อไม่มีการระบุเมล็ดและผ่านการสุ่ม (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