Copyright (c) 1994 W. Brainerd, C. Goldberg, and J. Adams.
All rights reserved.
This file may not be copied without permission of the authors.

Programmer's Guide to Fortran 90, 3rd Edition

Chapter 4 Arrays

4.6 Case Study: Calculating Probabilities

In Section 3.7, we considered the problem of calculating the probability that a throw of two dice will yield a 7 or an 11. The resulting program used the built-in subroutine random_number to generate a random number between 0 and 1. We now provide a slightly different solution using the same built-in procedure, but with an array as the first argument.

4.6.1 Generating an Array of Random Numbers

When the argument to the built-in subroutine random_number is a real array, the array is filled with a collection of real numbers each greater than or equal to 0 and less than 1. In general, the numbers are not all the same, although, by chance, some pairs of them might be equal.

Also, in this section, we will rewrite the subroutine random_int to return an array of integers from low to high. The subroutine random_int calls the built-in subroutine random_number, but now with an array as the argument. Note that the computational part of the subroutine is identical to the scalar version presented in Section 3.7.

subroutine random_int (result, low, high)

   integer, dimension (:), intent (out) :: result
   integer, intent (in) :: low, high
   real, dimension (size (result)) ::  &
         uniform_random_value

   call random_number (uniform_random_value)
   result =  &
   int ((high - low + 1) * uniform_random_value + low)

end subroutine random_int

Using the techniques discussed in Section 7.3.1, it is possible to make the subroutine random_int a generic subroutine, so that when it is called with a scalar first argument, it returns a single scalar value, and when it is called with an array first argument, it returns an array of pseudorandom integer values.

4.6.2 Computing the Probability of a 7 or 11 Using Arrays

Using the subroutine random_int, the program to estimate the probability of rolling 7 or 11 with two dice is a bit shorter than the scalar version. We leave it to the reader to ponder whether it is easier or more difficult to understand than the scalar version.

program seven_11

   implicit none
   integer, parameter :: number_of_rolls = 1000
   integer, dimension (number_of_rolls) ::  &
         dice, die_1, die_2
   integer :: wins

   call random_int (die_1, 1, 6)
   call random_int (die_2, 1, 6)
   dice = die_1 + die_2
   wins = count ((dice == 7) .or. (dice == 11))

   print "(a, f6.2)",  &
   "The percentage of rolls that are 7 or 11 is", &
   100.0 * real (wins) / real (number_of_rolls)

contains

subroutine random_int . . .
   . . .

end program seven_11

The built-in function count returns the number of true values in any logical array; in this case the value in the array is true if the corresponding value in the array dice is 7 or 11. This version of the program seven_11 should produce an answer similar to the one produced by the scalar version.

4.6.3 Exercises

  1. Use the array version of random_int to write a program that determines by simulation the percentage of times the sum of two rolled dice will be 2, 3, or 12.
  2. Two dice are rolled until a 4 or 7 comes up. Use the array version of random_int to write a simulation program to determine the percentage of times a 4 will be rolled before a 7 is rolled.
  3. Use the array version of random_int to write a simulation program to determine the percentage of times exactly 5 coins will be heads and 5 will be tails, if 10 fair coins are tossed simultaneously.
  4. Is it reasonable to use the array version of random_int to create a program that deals a five-card poker hand? Remember that the same card cannot occur twice in a hand.