⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 randomvar.html

📁 Shall高级编程
💻 HTML
📖 第 1 页 / 共 3 页
字号:
  73&nbsp;  }  74&nbsp;  75&nbsp;  76&nbsp;Play () {                    # Single pass (inner loop).  77&nbsp;i=0  78&nbsp;while [ "$i" -lt "$ROWS" ]       # One event per row.  79&nbsp;do  80&nbsp;  Move  81&nbsp;  ((i++));  82&nbsp;done  83&nbsp;  84&nbsp;SHIFT=11                     # Why 11, and not 10?  85&nbsp;let "POS += $SHIFT"          # Shift "zero position" to center.  86&nbsp;(( Slots[$POS]++ ))          # DEBUG: echo $POS  87&nbsp;  }  88&nbsp;  89&nbsp;  90&nbsp;Run () {                     # Outer loop.  91&nbsp;p=0  92&nbsp;while [ "$p" -lt "$PASSES" ]  93&nbsp;do  94&nbsp;  Play  95&nbsp;  (( p++ ))  96&nbsp;  POS=0                      # Reset to zero. Why?  97&nbsp;done  98&nbsp;  }  99&nbsp; 100&nbsp; 101&nbsp;# -------------- 102&nbsp;# main () 103&nbsp;Initialize_Slots 104&nbsp;Run 105&nbsp;Show_Slots 106&nbsp;# -------------- 107&nbsp; 108&nbsp;exit $? 109&nbsp; 110&nbsp;#  Exercises: 111&nbsp;#  --------- 112&nbsp;#  1) Show the results in a vertical bar graph, or as an alternative, 113&nbsp;#+    a scattergram. 114&nbsp;#  2) Alter the script to use /dev/urandom instead of $RANDOM. 115&nbsp;#     Will this make the results more random?</PRE></TD></TR></TABLE><HR></DIV><P>	<SPANCLASS="emphasis"><ICLASS="EMPHASIS">Jipe</I></SPAN> points out a set of techniques for	generating random numbers within a range.	<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#  Generate random number between 6 and 30.   2&nbsp;   rnumber=$((RANDOM%25+6))	   3&nbsp;   4&nbsp;#  Generate random number in the same 6 - 30 range,   5&nbsp;#+ but the number must be evenly divisible by 3.   6&nbsp;   rnumber=$(((RANDOM%30/3+1)*3))   7&nbsp;   8&nbsp;#  Note that this will not work all the time.   9&nbsp;#  It fails if $RANDOM%30 returns 0.  10&nbsp;  11&nbsp;#  Frank Wang suggests the following alternative:  12&nbsp;   rnumber=$(( RANDOM%27/3*3+6 ))</PRE></TD></TR></TABLE>	</P><P>	<SPANCLASS="emphasis"><ICLASS="EMPHASIS">Bill Gradwohl</I></SPAN> came up with an improved	formula that works for positive numbers.	<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))</PRE></TD></TR></TABLE>	</P><P>Here Bill presents a versatile function that returns	  a random number between two specified values.</P><DIVCLASS="EXAMPLE"><HR><ANAME="RANDOMBETWEEN"></A><P><B>Example 9-29. Random between values</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# random-between.sh   3&nbsp;# Random number between two specified values.    4&nbsp;# Script by Bill Gradwohl, with minor modifications by the document author.   5&nbsp;# Used with permission.   6&nbsp;   7&nbsp;   8&nbsp;randomBetween() {   9&nbsp;   #  Generates a positive or negative random number  10&nbsp;   #+ between $min and $max  11&nbsp;   #+ and divisible by $divisibleBy.  12&nbsp;   #  Gives a "reasonably random" distribution of return values.  13&nbsp;   #  14&nbsp;   #  Bill Gradwohl - Oct 1, 2003  15&nbsp;  16&nbsp;   syntax() {  17&nbsp;   # Function embedded within function.  18&nbsp;      echo  19&nbsp;      echo    "Syntax: randomBetween [min] [max] [multiple]"  20&nbsp;      echo  21&nbsp;      echo -n "Expects up to 3 passed parameters, "  22&nbsp;      echo    "but all are completely optional."  23&nbsp;      echo    "min is the minimum value"  24&nbsp;      echo    "max is the maximum value"  25&nbsp;      echo -n "multiple specifies that the answer must be "  26&nbsp;      echo     "a multiple of this value."  27&nbsp;      echo    "    i.e. answer must be evenly divisible by this number."  28&nbsp;      echo      29&nbsp;      echo    "If any value is missing, defaults area supplied as: 0 32767 1"  30&nbsp;      echo -n "Successful completion returns 0, "  31&nbsp;      echo     "unsuccessful completion returns"  32&nbsp;      echo    "function syntax and 1."  33&nbsp;      echo -n "The answer is returned in the global variable "  34&nbsp;      echo    "randomBetweenAnswer"  35&nbsp;      echo -n "Negative values for any passed parameter are "  36&nbsp;      echo    "handled correctly."  37&nbsp;   }  38&nbsp;  39&nbsp;   local min=${1:-0}  40&nbsp;   local max=${2:-32767}  41&nbsp;   local divisibleBy=${3:-1}  42&nbsp;   # Default values assigned, in case parameters not passed to function.  43&nbsp;  44&nbsp;   local x  45&nbsp;   local spread  46&nbsp;  47&nbsp;   # Let's make sure the divisibleBy value is positive.  48&nbsp;   [ ${divisibleBy} -lt 0 ] &#38;&#38; divisibleBy=$((0-divisibleBy))  49&nbsp;  50&nbsp;   # Sanity check.  51&nbsp;   if [ $# -gt 3 -o ${divisibleBy} -eq 0 -o  ${min} -eq ${max} ]; then   52&nbsp;      syntax  53&nbsp;      return 1  54&nbsp;   fi  55&nbsp;  56&nbsp;   # See if the min and max are reversed.  57&nbsp;   if [ ${min} -gt ${max} ]; then  58&nbsp;      # Swap them.  59&nbsp;      x=${min}  60&nbsp;      min=${max}  61&nbsp;      max=${x}  62&nbsp;   fi  63&nbsp;  64&nbsp;   #  If min is itself not evenly divisible by $divisibleBy,  65&nbsp;   #+ then fix the min to be within range.  66&nbsp;   if [ $((min/divisibleBy*divisibleBy)) -ne ${min} ]; then   67&nbsp;      if [ ${min} -lt 0 ]; then  68&nbsp;         min=$((min/divisibleBy*divisibleBy))  69&nbsp;      else  70&nbsp;         min=$((((min/divisibleBy)+1)*divisibleBy))  71&nbsp;      fi  72&nbsp;   fi  73&nbsp;  74&nbsp;   #  If max is itself not evenly divisible by $divisibleBy,  75&nbsp;   #+ then fix the max to be within range.  76&nbsp;   if [ $((max/divisibleBy*divisibleBy)) -ne ${max} ]; then   77&nbsp;      if [ ${max} -lt 0 ]; then  78&nbsp;         max=$((((max/divisibleBy)-1)*divisibleBy))  79&nbsp;      else  80&nbsp;         max=$((max/divisibleBy*divisibleBy))  81&nbsp;      fi  82&nbsp;   fi  83&nbsp;  84&nbsp;   #  ---------------------------------------------------------------------  85&nbsp;   #  Now, to do the real work.  86&nbsp;  87&nbsp;   #  Note that to get a proper distribution for the end points,  88&nbsp;   #+ the range of random values has to be allowed to go between  89&nbsp;   #+ 0 and abs(max-min)+divisibleBy, not just abs(max-min)+1.  90&nbsp;  91&nbsp;   #  The slight increase will produce the proper distribution for the  92&nbsp;   #+ end points.  93&nbsp;  94&nbsp;   #  Changing the formula to use abs(max-min)+1 will still produce  95&nbsp;   #+ correct answers, but the randomness of those answers is faulty in  96&nbsp;   #+ that the number of times the end points ($min and $max) are returned  97&nbsp;   #+ is considerably lower than when the correct formula is used.  98&nbsp;   #  ---------------------------------------------------------------------  99&nbsp; 100&nbsp;   spread=$((max-min)) 101&nbsp;   #  Omair Eshkenazi points out that this test is unnecessary, 102&nbsp;   #+ since max and min have already been switched around. 103&nbsp;   [ ${spread} -lt 0 ] &#38;&#38; spread=$((0-spread)) 104&nbsp;   let spread+=divisibleBy 105&nbsp;   randomBetweenAnswer=$(((RANDOM%spread)/divisibleBy*divisibleBy+min))    106&nbsp; 107&nbsp;   return 0 108&nbsp; 109&nbsp;   #  However, Paulo Marcel Coelho Aragao points out that 110&nbsp;   #+ when $max and $min are not divisible by $divisibleBy, 111&nbsp;   #+ the formula fails. 112&nbsp;   # 113&nbsp;   #  He suggests instead the following formula: 114&nbsp;   #    rnumber = $(((RANDOM%(max-min+1)+min)/divisibleBy*divisibleBy)) 115&nbsp; 116&nbsp;} 117&nbsp; 118&nbsp;# Let's test the function. 119&nbsp;min=-14 120&nbsp;max=20 121&nbsp;divisibleBy=3 122&nbsp; 123&nbsp; 124&nbsp;#  Generate an array of expected answers and check to make sure we get 125&nbsp;#+ at least one of each answer if we loop long enough. 126&nbsp; 127&nbsp;declare -a answer 128&nbsp;minimum=${min} 129&nbsp;maximum=${max} 130&nbsp;   if [ $((minimum/divisibleBy*divisibleBy)) -ne ${minimum} ]; then  131&nbsp;      if [ ${minimum} -lt 0 ]; then 132&nbsp;         minimum=$((minimum/divisibleBy*divisibleBy)) 133&nbsp;      else 134&nbsp;         minimum=$((((minimum/divisibleBy)+1)*divisibleBy)) 135&nbsp;      fi 136&nbsp;   fi 137&nbsp; 138&nbsp; 139&nbsp;   #  If max is itself not evenly divisible by $divisibleBy, 140&nbsp;   #+ then fix the max to be within range. 141&nbsp; 142&nbsp;   if [ $((maximum/divisibleBy*divisibleBy)) -ne ${maximum} ]; then  143&nbsp;      if [ ${maximum} -lt 0 ]; then 144&nbsp;         maximum=$((((maximum/divisibleBy)-1)*divisibleBy)) 145&nbsp;      else 146&nbsp;         maximum=$((maximum/divisibleBy*divisibleBy)) 147&nbsp;      fi 148&nbsp;   fi 149&nbsp; 150&nbsp; 151&nbsp;#  We need to generate only positive array subscripts, 152&nbsp;#+ so we need a displacement that that will guarantee 153&nbsp;#+ positive results. 154&nbsp; 155&nbsp;disp=$((0-minimum)) 156&nbsp;for ((i=${minimum}; i&#60;=${maximum}; i+=divisibleBy)); do 157&nbsp;   answer[i+disp]=0 158&nbsp;done 159&nbsp; 160&nbsp; 161&nbsp;# Now loop a large number of times to see what we get. 162&nbsp;loopIt=1000   #  The script author suggests 100000, 163&nbsp;              #+ but that takes a good long while. 164&nbsp; 165&nbsp;for ((i=0; i&#60;${loopIt}; ++i)); do 166&nbsp; 167&nbsp;   #  Note that we are specifying min and max in reversed order here to 168&nbsp;   #+ make the function correct for this case. 169&nbsp; 170&nbsp;   randomBetween ${max} ${min} ${divisibleBy} 171&nbsp; 172&nbsp;   # Report an error if an answer is unexpected. 173&nbsp;   [ ${randomBetweenAnswer} -lt ${min} -o ${randomBetweenAnswer} -gt ${max} ] \ 174&nbsp;   &#38;&#38; echo MIN or MAX error - ${randomBetweenAnswer}! 175&nbsp;   [ $((randomBetweenAnswer%${divisibleBy})) -ne 0 ] \ 176&nbsp;   &#38;&#38; echo DIVISIBLE BY error - ${randomBetweenAnswer}! 177&nbsp; 178&nbsp;   # Store the answer away statistically. 179&nbsp;   answer[randomBetweenAnswer+disp]=$((answer[randomBetweenAnswer+disp]+1)) 180&nbsp;done 181&nbsp; 182&nbsp; 183&nbsp; 184&nbsp;# Let's check the results 185&nbsp; 186&nbsp;for ((i=${minimum}; i&#60;=${maximum}; i+=divisibleBy)); do 187&nbsp;   [ ${answer[i+displacement]} -eq 0 ] \ 188&nbsp;   &#38;&#38; echo "We never got an answer of $i." \ 189&nbsp;   || echo "${i} occurred ${answer[i+displacement]} times." 190&nbsp;done 191&nbsp; 192&nbsp; 193&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>Just how random is <TTCLASS="VARNAME">$RANDOM</TT>? The best	  way to test this is to write a script that tracks	  the distribution of <SPANCLASS="QUOTE">"random"</SPAN> numbers	  generated by <TTCLASS="VARNAME">$RANDOM</TT>. Let's roll a	  <TTCLASS="VARNAME">$RANDOM</TT> die a few times . . .</P><DIVCLASS="EXAMPLE"><HR><ANAME="RANDOMTEST"></A><P><B>Example 9-30. Rolling a single die with RANDOM</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# How random is RANDOM?   3&nbsp;   4&nbsp;RANDOM=$$       # Reseed the random number generator using script process ID.   5&nbsp;   6&nbsp;PIPS=6          # A die has 6 pips.   7&nbsp;MAXTHROWS=600   # Increase this if you have nothing better to do with your time.   8&nbsp;throw=0         # Throw count.   9&nbsp;  10&nbsp;ones=0          #  Must initialize counts to zero,  11&nbsp;twos=0          #+ since an uninitialized variable is null, not zero.  12&nbsp;threes=0  13&nbsp;fours=0  14&nbsp;fives=0  15&nbsp;sixes=0  16&nbsp;  17&nbsp;print_result ()  18&nbsp;{  19&nbsp;echo  20&nbsp;echo "ones =   $ones"  21&nbsp;echo "twos =   $twos"  22&nbsp;echo "threes = $threes"  23&nbsp;echo "fours =  $fours"  24&nbsp;echo "fives =  $fives"  25&nbsp;echo "sixes =  $sixes"  26&nbsp;echo  27&nbsp;}  28&nbsp;  29&nbsp;update_count()  30&nbsp;{  31&nbsp;case "$1" in  32&nbsp;  0) let "ones += 1";;   # Since die has no "zero", this corresponds to 1.  33&nbsp;  1) let "twos += 1";;   # And this to 2, etc.  34&nbsp;  2) let "threes += 1";;  35&nbsp;  3) let "fours += 1";;  36&nbsp;  4) let "fives += 1";;  37&nbsp;  5) let "sixes += 1";;  38&nbsp;esac  39&nbsp;}  40&nbsp;  41&nbsp;echo  42&nbsp;  43&nbsp;  44&nbsp;while [ "$throw" -lt "$MAXTHROWS" ]  45&nbsp;do  46&nbsp;  let "die1 = RANDOM % $PIPS"  47&nbsp;  update_count $die1  48&nbsp;  let "throw += 1"  49&nbsp;done    50&nbsp;  51&nbsp;print_result  52&nbsp;  53&nbsp;exit 0  54&nbsp;  55&nbsp;#  The scores should distribute fairly evenly, assuming RANDOM is fairly random.  56&nbsp;#  With $MAXTHROWS at 600, all should cluster around 100, plus-or-minus 20 or so.  57&nbsp;#  58&nbsp;#  Keep in mind that RANDOM is a pseudorandom generator,  59&nbsp;#+ and not a spectacularly good one at that.  60&nbsp;  61&nbsp;#  Randomness is a deep and complex subject.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -