कैसे बैश में यादृच्छिक संख्या उत्पन्न करने के लिए?


236

कैसे बैश में एक सीमा के भीतर एक यादृच्छिक संख्या उत्पन्न करने के लिए?


21
कितनी यादृच्छिक होने की आवश्यकता है?
बोल्डन

जवाबों:


283

का उपयोग करें $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

20
यहां सावधान रहें। हालांकि यह चुटकी में ठीक है, यादृच्छिक संख्याओं पर अंकगणित करना नाटकीय रूप से आपके परिणाम की यादृच्छिकता को प्रभावित कर सकता है। के मामले में $RANDOM % 10, 8 और 9 औसत दर्जे का (हालांकि मामूली) 4-7 की तुलना में कम संभावित हैं, भले ही $RANDOMयादृच्छिक डेटा का एक मजबूत स्रोत है।
dimo414

3
@ dimo414 मैं "मामूली" के लिए उत्सुक हूं, क्या आपके पास कोई स्रोत है जहां मैं इस बारे में अधिक जानकारी पा सकता हूं?
पास्कलवूटन

58
अपने यादृच्छिक इनपुट को संशोधित करके, आप परिणाम " कबूतर- होलिंग" कर रहे हैं । के बाद से $RANDOMकी सीमा है 0-32767संख्या 0- 7करने के लिए नक्शे 3277विभिन्न संभव आदानों, लेकिन 8और 9केवल उत्पादन किया जा सकता 3276अलग अलग तरीकों से (क्योंकि 32768और 32769संभव नहीं हैं)। यह त्वरित हैक के लिए एक मामूली मुद्दा है, लेकिन इसका मतलब यह है कि परिणाम समान रूप से यादृच्छिक नहीं है। जावा की तरह रैंडम लाइब्रेरी, Randomदिए गए रेंज में एक समान यादृच्छिक संख्या को ठीक से वापस करने के लिए फ़ंक्शंस प्रदान करते हैं, न कि केवल एक-विभाज्य संख्या को मॉडरेट करने के बजाय।
dimo414

1
@JFSebastian बहुत सच है - modulo के साथ समस्या यह है कि किसी भी RNG की एकरूपता को तोड़ सकते हैं , न केवल खराब PRNG, बल्कि इसे बाहर बुलाने के लिए धन्यवाद।
dimo414 14

14
केवल संदर्भ के लिए,% 10 के लिए मूल कबूतर का अर्थ है 8 और 9 लगभग 0-3% 0–7 से कम होने की संभावना है। यदि आपकी शेल स्क्रिप्ट को उससे अधिक सटीक एकसमान यादृच्छिक संख्या की आवश्यकता है, तो हर तरह से अधिक जटिल और उचित तंत्र का उपयोग करें।
नेल्सन

70

कृपया देखें $RANDOM:

$RANDOM एक आंतरिक बैश फ़ंक्शन (स्थिर नहीं) है जो 0 - 32767 श्रेणी में एक छद्म आयामी पूर्णांक देता है। इसका उपयोग एन्क्रिप्शन कुंजी उत्पन्न करने के लिए नहीं किया जाना चाहिए।


1
क्या 32767किसी भी विशेष अर्थ नहीं है?
जिन क्वॉन

14
@JinKwon 32767है 2^16 / 2 - 1जो एक हस्ताक्षरित 16 बिट पूर्णांक के लिए ऊपरी सीमा है।
जेफरी मार्टिनेज 15

@ जीनकॉन आप स्पष्ट कर सकते हैं कि आप ऐसा क्यों नहीं कहते 2^15 - 1? यह समतुल्य है, इसलिए मैं कुछ उत्सुक हूं यदि मुझे कोई संदर्भ याद आ रहा है?
ब्रेट होल्मन

11
@BrettHolman मुझे लगता है कि वह हस्ताक्षरित 16 बिट पूर्णांक के "हस्ताक्षरित" भाग को इंगित करने की कोशिश कर रहा था। 2 ^ 16 मान, पोस्टिव और निगेटिव इन्ट्स के लिए आधे में विभाजित।
कोडी

यह उत्तर प्रश्न का उत्तर नहीं देता है।
ब्राट

48

आप शूफ (कोरुटिल्स में उपलब्ध) का भी उपयोग कर सकते हैं ।

shuf -i 1-100000 -n 1

रेंज अंत के रूप में आप var में कैसे पास होते हैं? मुझे यह मिल गया:shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
Dat tutbrus

1
$varश्रेणी के अंत के बजाय इस तरह जोड़ें :var=100 && shuf -i 1-${var} -n 1
knipwim

2
मैं इस विकल्प को पसंद करता हूं क्योंकि इसके साथ एन यादृच्छिक संख्या उत्पन्न करना आसान है -n। उदा। 1 और 100 के बीच 5 यादृच्छिक संख्याएँ उत्पन्न करें :shuf -i 1-100 -n 5
एरिजन

जहां तक ​​मैं समझता हूं कि संख्याएं यादृच्छिक नहीं हैं। यदि आप निर्दिष्ट करते हैं shuf -i 1-10 -n 10तो आपको 1 से 10 तक सभी नंबर मिलेंगे। यदि आप निर्दिष्ट करते हैं -n 15तो आपको अभी भी केवल 10 नंबर एक ही बार मिलेंगे। यह वास्तव में केवल फेरबदल है, यादृच्छिक संख्या उत्पन्न नहीं कर रहा है।
13

प्रतिस्थापन के साथ यादृच्छिक संख्या प्राप्त करने के लिए: -r
ज्योफ्री एंडरसन

36

इसे अपने शेल से आज़माएं:

$ od -A n -t d -N 1 /dev/urandom

यहां, -t dनिर्दिष्ट करता है कि आउटपुट प्रारूप पर हस्ताक्षर किए जाने वाले दशमलव होने चाहिए; -N 1से एक बाइट पढ़ने के लिए कहते हैं /dev/urandom


2
सवाल एक सीमा में संख्या के लिए पूछता है।
जेएसकमोर

9
आप रिक्त स्थान निकाल सकते हैं:od -A n -t d -N 1 /dev/urandom |tr -d ' '
रॉबर्ट

23

तुम भी awk से यादृच्छिक संख्या प्राप्त कर सकते हैं

awk 'BEGIN {
   # seed
   srand()
   for (i=1;i<=1000;i++){
     print int(1 + rand() * 100)
   }
}'

1
+1 आप जानते हैं, पहले मैं हालांकि आप इसे इस तरह से क्यों करना चाहते हैं, लेकिन वास्तव में मुझे यह काफी पसंद है।
zelanix

1
एक समाधान देने के लिए धन्यवाद जिसमें बीजारोपण शामिल है। मुझे यह कहीं नहीं मिला!
so.very.tired 10:23 बजे

2
बीजारोपण के लिए +1। यह उल्लेखनीय है कि srand()बीज वर्तमान सीपीयू समय है। यदि आपको एक विशिष्ट बीज निर्दिष्ट करने की आवश्यकता है, तो आरएनजी को डुप्लिकेट किया जा सकता है, srand(x)जहां xबीज है वहां का उपयोग करें । इसके अलावा, GNU awk के संख्यात्मक फ़ंक्शन मैनुअल के हवाले से कहा गया है, "विभिन्न awk कार्यान्वयन आंतरिक रूप से विभिन्न यादृच्छिक-संख्या जनरेटर का उपयोग करते हैं।" उत्थान यह है कि यदि आप सांख्यिकीय वितरण पैदा करने में रुचि रखते हैं, तो आपको अलग-अलग प्लेटफ़ॉर्म पर एक रनटाइम से अगले तक जाने वाले मामूली बदलावों की उम्मीद करनी चाहिए (सभी चल रहे हैं awkया gawk)।
Cbhihe

18

$ रंडोम है। मुझे नहीं पता कि यह कैसे काम करता है। लेकिन यह काम करता है। परीक्षण के लिए, आप कर सकते हैं:

echo $RANDOM

17

मुझे यह चाल पसंद है:

echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99

...


6
$ RANDOM 0 - 32767 की सीमा में है। आप अधिक संख्याओं के साथ समाप्त होंगे जो 1, 2 या 3 से शुरू होते हैं, आप 4-9 की तुलना में। यदि आप एक असंतुलित वितरण के साथ ठीक हैं, तो यह ठीक काम करेगा।
jbo5112

2
@ jbo5112 आप पूरी तरह से सही हैं, डिस्प्ले के आखिरी अंक के बारे में क्या? गूंज $ {RANDOM: 0-1} एक अंक के लिए, $ {RANDOM: 0-2} दो अंकों के लिए ...?
9

3
यदि आप अंतिम अंक का उपयोग करते हैं, तो यह अच्छा होगा, लेकिन इसमें 0 और 00 का समावेश होगा। एक ही अंक पर, 0-4 8-9 से अधिक बार 0.03% घटित होगा। 2 अंकों पर, 0-67 68-99 की तुलना में 0.3% अधिक बार होगा। यदि आपको एक यादृच्छिक संख्या वितरण की आवश्यकता है जो अच्छा है, तो उम्मीद है कि आप बैश का उपयोग नहीं कर रहे हैं। मूल के साथ: आपके ${RANDOM:0:1}पास 1 या 2 देने का 67.8% मौका है, ${RANDOM:0:2}केवल आपके पास एक अंकों की संख्या देने का 0.03% मौका है (1% होना चाहिए), और दोनों में आपको 0 देने का 0.003% मौका है। अभी भी ऐसे मामलों का उपयोग करते हैं जहां यह ठीक है (जैसे गैर-सुसंगत इनपुट)।
jbo5112

12

यादृच्छिक संख्या 0 और 9 के बीच समावेशी।

echo $((RANDOM%10))

2
मेरे बुरे, मैन पेज को ठीक से नहीं पढ़ा। $RANDOMकेवल 0 से 32767 तक चला जाता है। यह कहा जाना चाहिए "रैंडम संख्या ज्यादातर 1 और 3 के बीच, कुछ विंगर्स के साथ";)
डेविड न्यूकोम्ब

1
क्या? यह अभी भी 0 और 9 के बीच होगा, हालांकि 8 और 9 में 7 के माध्यम से 0 से होने की थोड़ी कम संभावना होगी, जैसा कि एक अन्य उत्तर में बताया गया है।
किनी

6

यदि आप एक Linux सिस्टम का उपयोग कर रहे हैं, तो आप एक यादृच्छिक संख्या / dev / random या / dev / urandom से प्राप्त कर सकते हैं । यदि पर्याप्त रैंडम नंबर उपलब्ध नहीं हैं, तो केयरफुल / देव / रैंडम ब्लॉक करेंगे। यदि आपको रैंडमनेस के उपयोग की गति की आवश्यकता है / dev / urandom।

ये "फाइलें" ऑपरेटिंग सिस्टम द्वारा उत्पन्न यादृच्छिक संख्याओं से भरी होंगी। यदि आप सही या छद्म यादृच्छिक संख्या प्राप्त करते हैं तो यह आपके सिस्टम पर / dev / random के कार्यान्वयन पर निर्भर करता है। माउस, हार्ड ड्राइव, नेटवर्क जैसे डिवाइस ड्राइवरों से एकत्रित किए गए हेल्प फॉर्म शोर से ट्रू रैंडम नंबर उत्पन्न होते हैं।

आप dd के साथ फाइल से रैंडम नंबर प्राप्त कर सकते हैं


5

मैंने इनमें से कुछ विचारों को लिया है और एक फ़ंक्शन बनाया है जो बहुत सारे यादृच्छिक संख्याओं की आवश्यकता होने पर जल्दी से प्रदर्शन करना चाहिए।

odयदि आपको बहुत सारे रैंडम नंबर चाहिए तो कॉलिंग महंगी है। इसके बजाय मैं इसे एक बार कॉल करता हूं और 1024 यादृच्छिक संख्याओं को / dev / urandom से स्टोर करता हूं। कब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

अद्यतन: यह सभी एन के लिए इतनी अच्छी तरह से काम नहीं करता है। यह छोटे एन के साथ उपयोग किए जाने पर यादृच्छिक बिट्स को भी बर्बाद करता है। ध्यान दें कि (इस मामले में) एक 32 बिट यादृच्छिक संख्या 0 और 9 (10 * 9) के बीच 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

मैंने यह कोशिश की - यह 100% सीपीयू के 10 सेकंड लेता है और फिर 10 नंबर मुद्रित करता है जो सभी पर यादृच्छिक नहीं दिखता।
कार्लो वुड

मुझे अब याद आया। यह कोड 100,000 यादृच्छिक संख्या उत्पन्न करता है। यह प्रत्येक को एक 'बिन' में डालता है कि यह कितना यादृच्छिक है। 10 डिब्बे हैं। ये संख्या समान होनी चाहिए यदि 0 और 9 के बीच प्रत्येक यादृच्छिक संख्या समान रूप से होने की संभावना है। आप प्रत्येक संख्या मुद्रित करने के लिए चाहते हैं, $ आरईटी RANDBETWEEN से 10 के बाद गूंज
philcolbourn

od -An -tu4 -N40 /dev/urandomव्हॉट्सएप के साथ अलग किए गए 10 यादृच्छिक अहस्ताक्षरित 32 बिट पूर्णांक उत्पन्न करेंगे। आप इसे एक सरणी में संग्रहीत कर सकते हैं और बाद में इसका उपयोग कर सकते हैं। आपका कोड एक ओवरकिल लगता है।
अली

@ अल, ओपी ने यह निर्दिष्ट नहीं किया कि वे 32 बिट चाहते थे और न ही किसी अन्य आकार की यादृच्छिक संख्या। मैंने और कुछ अन्य लोगों ने इस प्रश्न की व्याख्या एक सीमा के भीतर एक यादृच्छिक संख्या प्रदान करने के रूप में की। मेरा रैंड फ़ंक्शन इस लक्ष्य को प्राप्त करता है और एन्ट्रापी के नुकसान को भी कम करता है, जो कि थका हुआ होने पर, कार्यक्रमों को अवरुद्ध करने का कारण बनता है। od / on / dev / urandom केवल 2 ^ N बिट रैंडम नंबर देता है और ओपी को तब एक सरणी में कई मानों को स्टोर करने की जरूरत होती है, क्रमिक रूप से उन्हें इस एरे से निकाला जाता है, और इस एरे को फिर से भरना होता है। शायद आप इसे एक उत्तर के रूप में कोड कर सकते हैं और अन्य यादृच्छिक संख्या सीमाओं को संभाल सकते हैं?
दार्शनिकोवन

@philcolbourn, आप ओपी के बारे में सही नहीं बता रहे हैं कि वह किस तरह का रैंडम नंबर चाहता है और इससे मेरा ध्यान भटक गया। लेकिन उन्होंने केवल यह पूछा: " बैश में एक यादृच्छिक संख्या कैसे उत्पन्न करें ?"। मेरा कहना है कि उसने केवल एक यादृच्छिक संख्या के लिए पूछा। यद्यपि यह आलोचक मेरी पिछली टिप्पणी ( 10 यादृच्छिक संख्याएँ) को भी लागू करता है।
अली

5

/ Dev / random / / dev / urandom character विशेष फाइलों से पढ़ना जाने का रास्ता है।

ये डिवाइस पढ़े जाने पर सही मायने में रैंडम नंबर देते हैं और एप्लिकेशन सॉफ़्टवेयर को एन्क्रिप्शन के लिए सुरक्षित कुंजी चुनने में मदद करने के लिए डिज़ाइन किए जाते हैं। ऐसे यादृच्छिक संख्याओं को एक एंट्रॉपी पूल से निकाला जाता है जो विभिन्न यादृच्छिक घटनाओं द्वारा योगदान दिया जाता है। {LDD3, जोनाथन कोरबेट, एलेसेंड्रो रुबीनी और ग्रेग क्रोहा-हार्टमैन]

ये दो फाइलें विशेष रूप से कर्नेल रैंडमाइजेशन के लिए इंटरफेस हैं

void get_random_bytes_arch(void* buf, int nbytes)

जो हार्डवेयर से सही मायने में यादृच्छिक बाइट्स खींचता है यदि ऐसा फ़ंक्शन हार्डवेयर द्वारा कार्यान्वित किया जाता है (आमतौर पर), या यह एन्ट्रॉपी पूल (माउस और कीबोर्ड के बीच की घटनाओं के बीच का समय शामिल होता है और अन्य बाधाएं जो SA_AMPLE_RANDOM के साथ पंजीकृत होती हैं) से आती हैं।

dd if=/dev/urandom count=4 bs=1 | od -t d

यह काम करता है, लेकिन अनावश्यक आउटपुट ddको स्टडआउट से लिखता है । नीचे दी गई कमांड मुझे केवल पूर्णांक की आवश्यकता है। मैं भी यादृच्छिक बिट्स की निर्दिष्ट संख्या प्राप्त कर सकता हूं क्योंकि मुझे अंकगणित के विस्तार के लिए दिए गए बिटमास्क के समायोजन की आवश्यकता है:

me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump 
                         -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))

3

व्हाट अबाउट:

perl -e 'print int rand 10, "\n"; '

क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक संख्या के लिए, आपको / dev / urandom से पढ़ना होगा या Crypt :: Random लाइब्रेरी का उपयोग करना होगा।
kh

3

शायद मुझे थोड़ी देर हो गई है, लेकिन jotबैश में एक सीमा के भीतर एक यादृच्छिक संख्या उत्पन्न करने के लिए उपयोग करने के बारे में क्या ?

jot -r -p 3 1 0 1

यह -r3 दशमलव स्थानों पर सटीक ( -p) के साथ एक यादृच्छिक ( ) संख्या उत्पन्न करता है । इस विशेष स्थिति में, आपको 0 और 1 ( 1 0 1) के बीच एक नंबर मिलेगा । आप अनुक्रमिक डेटा भी प्रिंट कर सकते हैं। मैनुअल के अनुसार यादृच्छिक संख्या का स्रोत है:

जब कोई बीज निर्दिष्ट नहीं किया जाता है, और यादृच्छिक (3) के माध्यम से रैंडम संख्या (3) के माध्यम से यादृच्छिक संख्या प्राप्त की जाती है।


स्थापित होना चाहिए: sudo apt इंस्टॉल एथेना-जोट
xerostomus

3

@ नेल्सन, @ ​​बरुण और @ रोबर्ट के शानदार जवाबों के आधार पर, यहां एक बैश स्क्रिप्ट है जो यादृच्छिक संख्या उत्पन्न करती है।

  • आप कितने अंक उत्पन्न कर सकते हैं।
  • प्रत्येक अंक को अलग से उत्पन्न किया जाता है, /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

वास्तव में मैं क्या था।
प्रोमेथियस

2

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

किसी प्रोग्राम की रैंडम ब्रांचिंग या हाँ / नहीं; 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.