Advertisement
bmote

cannon.sh

Jan 10th, 2012
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 4.04 KB | None | 0 0
  1. #!/bin/bash
  2. # cannon.sh: Approximating PI by firing cannonballs.
  3.  
  4. # This is a very simple instance of a "Monte Carlo" simulation:
  5. #+ a mathematical model of a real-life event,
  6. #+ using pseudorandom numbers to emulate random chance.
  7.  
  8. #  Consider a perfectly square plot of land, 10000 units on a side.
  9. #  This land has a perfectly circular lake in its center,
  10. #+ with a diameter of 10000 units.
  11. #  The plot is actually mostly water, except for land in the four corners.
  12. #  (Think of it as a square with an inscribed circle.)
  13. #
  14. #  We will fire iron cannonballs from an old-style cannon
  15. #+ at the square.
  16. #  All the shots impact somewhere on the square,
  17. #+ either in the lake or on the dry corners.
  18. #  Since the lake takes up most of the area,
  19. #+ most of the shots will SPLASH! into the water.
  20. #  Just a few shots will THUD! into solid ground
  21. #+ in the four corners of the square.
  22. #
  23. #  If we take enough random, unaimed shots at the square,
  24. #+ Then the ratio of SPLASHES to total shots will approximate
  25. #+ the value of PI/4.
  26. #
  27. #  The reason for this is that the cannon is actually shooting
  28. #+ only at the upper right-hand quadrant of the square,
  29. #+ i.e., Quadrant I of the Cartesian coordinate plane.
  30. #  (The previous explanation was a simplification.)
  31. #
  32. #  Theoretically, the more shots taken, the better the fit.
  33. #  However, a shell script, as opposed to a compiled language
  34. #+ with floating-point math built in, requires a few compromises.
  35. #  This tends to lower the accuracy of the simulation, of course.
  36.  
  37.  
  38. DIMENSION=10000  # Length of each side of the plot.
  39.                  # Also sets ceiling for random integers generated.
  40.  
  41. MAXSHOTS=1000    # Fire this many shots.
  42.                  # 10000 or more would be better, but would take too long.
  43. PMULTIPLIER=4.0  # Scaling factor to approximate PI.
  44.  
  45. get_random ()
  46. {
  47. SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')
  48. RANDOM=$SEED                                  #  From "seeding-random.sh"
  49.                                               #+ example script.
  50. let "rnum = $RANDOM % $DIMENSION"             #  Range less than 10000.
  51. echo $rnum
  52. }
  53.  
  54. distance=        # Declare global variable.
  55. hypotenuse ()    # Calculate hypotenuse of a right triangle.
  56. {                # From "alt-bc.sh" example.
  57. distance=$(bc -l << EOF
  58. scale = 0
  59. sqrt ( $1 * $1 + $2 * $2 )
  60. EOF
  61. )
  62. #  Setting "scale" to zero rounds down result to integer value,
  63. #+ a necessary compromise in this script.
  64. #  This diminshes the accuracy of the simulation, unfortunately.
  65. }
  66.  
  67.  
  68. # main() {
  69.  
  70. # Initialize variables.
  71. shots=0
  72. splashes=0
  73. thuds=0
  74. Pi=0
  75.  
  76. while [ "$shots" -lt  "$MAXSHOTS" ]           # Main loop.
  77. do
  78.  
  79.   xCoord=$(get_random)                        # Get random X and Y coords.
  80.   yCoord=$(get_random)
  81.   hypotenuse $xCoord $yCoord                  #  Hypotenuse of right-triangle =
  82.                                               #+ distance.
  83.   ((shots++))
  84.  
  85.   printf "#%4d   " $shots
  86.   printf "Xc = %4d  " $xCoord
  87.   printf "Yc = %4d  " $yCoord
  88.   printf "Distance = %5d  " $distance         #  Distance from
  89.                                               #+ center of lake --
  90.                                               #  the "origin" --
  91.                                               #+ coordinate (0,0).
  92.  
  93.   if [ "$distance" -le "$DIMENSION" ]
  94.   then
  95.     echo -n "SPLASH!  "
  96.     ((splashes++))
  97.   else
  98.     echo -n "THUD!    "
  99.     ((thuds++))
  100.   fi
  101.  
  102.   Pi=$(echo "scale=9; $PMULTIPLIER*$splashes/$shots" | bc)
  103.   # Multiply ratio by 4.0.
  104.   echo -n "PI ~ $Pi"
  105.   echo
  106.  
  107. done
  108.  
  109. echo
  110. echo "After $shots shots, PI looks like approximately $Pi."
  111. # Tends to run a bit high . . .
  112. # Probably due to round-off error and imperfect randomness of $RANDOM.
  113. echo
  114.  
  115. # }
  116.  
  117. exit 0
  118.  
  119. #  One might well wonder whether a shell script is appropriate for
  120. #+ an application as complex and computation-intensive as a simulation.
  121. #
  122. #  There are at least two justifications.
  123. #  1) As a proof of concept: to show it can be done.
  124. #  2) To prototype and test the algorithms before rewriting
  125. #+    it in a compiled high-level language.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement