Câu trả lời:
Sử dụng $RANDOM
. Nó thường hữu ích khi kết hợp với số học shell đơn giản. Chẳng hạn, để tạo một số ngẫu nhiên trong khoảng từ 1 đến 10 (đã bao gồm):
$ echo $((1 + RANDOM % 10))
3
Máy phát điện thực tế là trong variables.c
, chức năng brand()
. Các phiên bản cũ hơn là một máy phát tuyến tính đơn giản. Phiên bản 4.0 bash
sử dụng một trình tạo với một trích dẫn đến một bài báo năm 1985, có lẽ có nghĩa là nó là một nguồn số giả ngẫu nhiên. Tôi sẽ không sử dụng nó cho một mô phỏng (và chắc chắn không phải cho tiền điện tử), nhưng có lẽ nó đủ cho các tác vụ kịch bản cơ bản.
Nếu bạn đang làm một cái gì đó yêu cầu số ngẫu nhiên nghiêm trọng, bạn có thể sử dụng /dev/random
hoặc /dev/urandom
nếu chúng có sẵn:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
, 8 và 9 có thể đo lường được (mặc dù không đáng kể) ít có thể xảy ra hơn 0-7, ngay cả khi đó $RANDOM
là một nguồn dữ liệu ngẫu nhiên mạnh mẽ.
$RANDOM
phạm vi là 0-32767
các số 0
- 7
ánh xạ tới 3277
các đầu vào có thể khác nhau, nhưng 8
và 9
chỉ có thể được tạo ra theo 3276
các cách khác nhau (vì 32768
và 32769
không thể). Đây là một vấn đề nhỏ đối với hack nhanh, nhưng có nghĩa là kết quả không ngẫu nhiên thống nhất. Các thư viện ngẫu nhiên, như của Java Random
, cung cấp các hàm để trả về đúng một số ngẫu nhiên thống nhất trong phạm vi đã cho, thay vì chỉ đơn giản là sửa đổi một số không chia được.
Vui lòng xem $RANDOM
:
$RANDOM
là một hàm Bash nội bộ (không phải là hằng số) trả về số nguyên giả trong phạm vi 0 - 32767. Không nên sử dụng nó để tạo khóa mã hóa.
32767
ý nghĩa đặc biệt nào không?
32767
là 2^16 / 2 - 1
giới hạn trên cho số nguyên 16 bit đã ký.
2^15 - 1
? Nó tương đương nhau, vì vậy tôi chỉ tò mò nếu có một số bối cảnh tôi đang thiếu?
Bạn cũng có thể sử dụng shuf (có sẵn trong 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
thay vì kết thúc phạm vi, như thế này:var=100 && shuf -i 1-${var} -n 1
-n
. Ví dụ: Tạo 5 số ngẫu nhiên trong khoảng từ 1 đến 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
bạn sẽ nhận được tất cả các số từ 1 đến 10 chính xác một. Nếu bạn chỉ định, -n 15
bạn vẫn sẽ chỉ nhận được 10 số đó chính xác một lần. Đó thực sự chỉ là xáo trộn, không tạo ra số ngẫu nhiên.
bạn cũng có thể nhận được số ngẫu nhiên từ awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
là hạt giống của nó là thời gian CPU hiện tại. Nếu bạn cần phải xác định một hạt giống cụ thể, vì vậy RNG có thể được nhân đôi, sử dụng srand(x)
ở đâu x
là hạt giống. Ngoài ra, được trích dẫn từ sổ tay chức năng số của GNU awk, "các triển khai awk khác nhau sử dụng các trình tạo số ngẫu nhiên khác nhau trong nội bộ." Kết quả cuối cùng là nếu bạn quan tâm đến việc tạo phân phối thống kê, bạn nên mong đợi các biến thể nhẹ đi từ thời gian chạy này sang thời gian tiếp theo trên nền tảng khác nhau (tất cả đang chạy awk
hoặc gawk
).
Có $ RANDOM. Tôi không biết chính xác làm thế nào nó hoạt động. Nhưng nó đã có tác dụng. Để thử nghiệm, bạn có thể làm:
echo $RANDOM
Tôi thích thủ thuật này:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
có 67,8% cơ hội cho bạn 1 hoặc 2, ${RANDOM:0:2}
chỉ có 0,03% cơ hội cho bạn một số có một chữ số (nên là 1%) và cả hai đều có 0,003% cơ hội cho bạn 0 Vẫn có những trường hợp sử dụng trong trường hợp này là tốt (ví dụ: đầu vào không nhất quán).
Số ngẫu nhiên từ 0 đến 9 đã bao gồm.
echo $((RANDOM%10))
$RANDOM
chỉ đi từ 0 đến 32767. Đáng lẽ nên nói "Số ngẫu nhiên chủ yếu nằm trong khoảng từ 1 đến 3, với một vài người chạy cánh";)
Nếu bạn đang sử dụng hệ thống linux, bạn có thể nhận được một số ngẫu nhiên trong số / dev / ngẫu nhiên hoặc / dev / urandom. Hãy cẩn thận / dev / ngẫu nhiên sẽ chặn nếu không có đủ số ngẫu nhiên có sẵn. Nếu bạn cần tốc độ trên ngẫu nhiên, hãy sử dụng / dev / urandom.
Các "tệp" này sẽ được lấp đầy với các số ngẫu nhiên được tạo bởi hệ điều hành. Nó phụ thuộc vào việc triển khai / dev / ngẫu nhiên trên hệ thống của bạn nếu bạn nhận được các số ngẫu nhiên đúng hoặc giả. Các số ngẫu nhiên thực sự được tạo ra với sự trợ giúp hình thành tiếng ồn được thu thập từ trình điều khiển thiết bị như chuột, ổ cứng, mạng.
Bạn có thể nhận được số ngẫu nhiên từ tệp với dd
Tôi đã lấy một vài trong số những ý tưởng này và thực hiện một chức năng sẽ thực hiện nhanh chóng nếu cần nhiều số ngẫu nhiên.
Gọi od
là đắt tiền nếu bạn cần nhiều số ngẫu nhiên. Thay vào đó tôi gọi nó một lần và lưu trữ 1024 số ngẫu nhiên từ / dev / urandom. Khi nàorand
được gọi, số ngẫu nhiên cuối cùng được trả về và chia tỷ lệ. Sau đó nó được xóa khỏi bộ nhớ cache. Khi bộ đệm trống, 1024 số ngẫu nhiên khác được đọc.
Thí dụ:
rand 10; echo $RET
Trả về một số ngẫu nhiên trong RET trong khoảng từ 0 đến 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
CẬP NHẬT: Điều đó không hoạt động tốt cho tất cả N. Nó cũng lãng phí các bit ngẫu nhiên nếu được sử dụng với N. nhỏ Lưu ý rằng (trong trường hợp này) một số ngẫu nhiên 32 bit có đủ entropy cho 9 số ngẫu nhiên trong khoảng từ 0 đến 9 (10 * 9 = 1.000.000.000 <= 2 * 32) chúng tôi có thể trích xuất nhiều số ngẫu nhiên từ mỗi giá trị nguồn ngẫu nhiên 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
sẽ tạo ra 10 số nguyên 32 bit không dấu ngẫu nhiên được phân tách bằng khoảng trắng. bạn có thể lưu trữ nó trong một mảng và sử dụng nó sau đó. mã của bạn dường như là một quá mức cần thiết.
Đọc từ các tập tin đặc biệt của nhân vật / dev / ngẫu nhiên hoặc / dev / urandom là cách tốt nhất.
Các thiết bị này trả về số thực sự ngẫu nhiên khi đọc và được thiết kế để giúp phần mềm ứng dụng chọn khóa bảo mật để mã hóa. Các số ngẫu nhiên như vậy được trích xuất từ một nhóm entropy được đóng góp bởi các sự kiện ngẫu nhiên khác nhau. {LDD3, Jonathan Corbet, Alessandro Rubini và Greg Kroah-Hartman]
Hai tệp này là giao diện cho ngẫu nhiên kernel, đặc biệt
void get_random_bytes_arch(void* buf, int nbytes)
sẽ rút các byte thực sự ngẫu nhiên từ phần cứng nếu chức năng đó là do phần cứng được triển khai (thường là) hoặc nó rút ra từ nhóm entropy (bao gồm các khoảng thời gian giữa các sự kiện như gián đoạn chuột và bàn phím và các ngắt khác được đăng ký với SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Điều này hoạt động, nhưng viết đầu ra không cần thiết từ dd
thiết bị xuất chuẩn. Lệnh dưới đây chỉ cung cấp số nguyên tôi cần. Tôi thậm chí có thể nhận được số bit ngẫu nhiên được chỉ định khi tôi cần bằng cách điều chỉnh bitmask được cung cấp để mở rộng số học:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Có lẽ tôi hơi muộn, nhưng còn việc sử dụng jot
để tạo một số ngẫu nhiên trong phạm vi trong Bash thì sao?
jot -r -p 3 1 0 1
Điều này tạo ra một số ngẫu nhiên ( -r
) với độ chính xác 3 chữ số thập phân ( -p
). Trong trường hợp cụ thể này, bạn sẽ nhận được một số từ 0 đến 1 ( 1 0 1
). Bạn cũng có thể in dữ liệu tuần tự. Nguồn của số ngẫu nhiên, theo hướng dẫn, là:
Số ngẫu nhiên thu được thông qua arc4random (3) khi không có hạt giống nào được chỉ định và thông qua ngẫu nhiên (3) khi hạt giống được đưa ra.
Dựa trên các câu trả lời tuyệt vời của @Nelson, @Barun và @Robert, đây là tập lệnh Bash tạo ra các số ngẫu nhiên.
/dev/urandom
đó là tốt hơn nhiều so với Bash tích hợp trong$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
Tạo số ngẫu nhiên trong phạm vi từ 0 đến n (số nguyên 16 bit đã ký). Kết quả được đặt trong biến $ RAND. Ví dụ:
#!/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
Phân nhánh ngẫu nhiên của một chương trình hoặc có / không; 1/0; đầu ra đúng / sai:
if [ $RANDOM -gt 16383 ]; then # 16383 = 32767/2
echo var=true/1/yes/go_hither
else
echo var=false/0/no/go_thither
fi
nếu bạn lười nhớ 16383:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi