Dokumentasi Bash mengatakan bahwa setiap kali $RANDOM
direferensikan, angka acak antara 0 dan 32767 dikembalikan. Jika kami menjumlahkan dua referensi berturut-turut, kami mendapatkan nilai dari 0 hingga 65534, yang mencakup kisaran 63001 kemungkinan yang diinginkan untuk angka acak antara 2000 dan 65000.
Untuk menyesuaikannya dengan rentang yang tepat, kami menggunakan jumlah modulo 63001, yang akan memberi kami nilai dari 0 hingga 63000. Ini pada gilirannya hanya membutuhkan kenaikan pada tahun 2000 untuk memberikan angka acak yang diinginkan, antara 2000 dan 65000. Ini bisa menjadi diringkas sebagai berikut:
port=$((((RANDOM + RANDOM) % 63001) + 2000))
Pengujian
# Generate random numbers and print the lowest and greatest found
test-random-max-min() {
max=2000
min=65000
for i in {1..10000}; do
port=$((((RANDOM + RANDOM) % 63001) + 2000))
echo -en "\r$port"
[[ "$port" -gt "$max" ]] && max="$port"
[[ "$port" -lt "$min" ]] && min="$port"
done
echo -e "\rMax: $max, min: $min"
}
# Sample output
# Max: 64990, min: 2002
# Max: 65000, min: 2004
# Max: 64970, min: 2000
Ketepatan perhitungan
Berikut ini adalah uji penuh, brute-force untuk kebenaran perhitungan. Program ini hanya mencoba untuk menghasilkan semua 63001 kemungkinan berbeda secara acak, menggunakan perhitungan yang sedang diuji. The --jobs
parameter harus membuatnya berjalan lebih cepat, tapi tidak deterministik (total kemungkinan dihasilkan mungkin lebih rendah dari 63.001).
test-all() {
start=$(date +%s)
find_start=$(date +%s)
total=0; ports=(); i=0
rm -f ports/ports.* ports.*
mkdir -p ports
while [[ "$total" -lt "$2" && "$all_found" != "yes" ]]; do
port=$((((RANDOM + RANDOM) % 63001) + 2000)); i=$((i+1))
if [[ -z "${ports[port]}" ]]; then
ports["$port"]="$port"
total=$((total + 1))
if [[ $((total % 1000)) == 0 ]]; then
echo -en "Elapsed time: $(($(date +%s) - find_start))s \t"
echo -e "Found: $port \t\t Total: $total\tIteration: $i"
find_start=$(date +%s)
fi
fi
done
all_found="yes"
echo "Job $1 finished after $i iterations in $(($(date +%s) - start))s."
out="ports.$1.txt"
[[ "$1" != "0" ]] && out="ports/$out"
echo "${ports[@]}" > "$out"
}
say-total() {
generated_ports=$(cat "$@" | tr ' ' '\n' | \sed -E s/'^([0-9]{4})$'/'0\1'/)
echo "Total generated: $(echo "$generated_ports" | sort | uniq | wc -l)."
}
total-single() { say-total "ports.0.txt"; }
total-jobs() { say-total "ports/"*; }
all_found="no"
[[ "$1" != "--jobs" ]] && test-all 0 63001 && total-single && exit
for i in {1..1000}; do test-all "$i" 40000 & sleep 1; done && wait && total-jobs
Untuk menentukan berapa banyak iterasi yang diperlukan untuk mendapatkan probabilitas tertentu p/q
dari semua 63001 kemungkinan yang telah dihasilkan, saya percaya kita bisa menggunakan ungkapan di bawah ini. Sebagai contoh, di sini adalah perhitungan untuk probabilitas lebih besar dari 1/2 , dan di sini untuk lebih dari 9/10 .
shuf
ini relatif baru - saya telah melihatnya di sistem Ubuntu dalam beberapa tahun terakhir tetapi tidak RHEL / CentOS saat ini.