In order to fully understand and visualize the distribution of the generated numbers, we break the (min, max) range into smaller subintervals, call them bins and compute the percentage of our numbers that fall in each. These percentages can be printed, or better yet, plotted.
In this lab, we want to develop a structured system to address the above requirement in a flexible and comprehensive way. The system should be designed so that no implicit assumptions are made re the number of numbers, their range, nor the width of each bin. We will assume, and hard-code, however, that the number of bins is 50 and that N does not exceed 100,000. Here is a sample log of how this sought system should run:
How many numbers to generate? 100000 Range: Enter the min and max values ... -1000. 5000. Enter distribution type: 1=UNIFORM (default), 2=NORMAL 2 Enter average and standard deviation 1500. 600. 8% | * 7% | ***** 6% | ******* 5% | ********** 4% | ************ 3% | ************** 2% | ***************** 1% | ******************** 0% |************************************************** |-------------------------------------------------- -1000. 5000.
As you can see, all the parameters (except the number of bins) are entered by the user. The final output is a Fortran-generated chart (i.e. not from Excel) that plots the computed percentages versus the 50 bins. The chart has the following characteristics:
Here is the main program:
program Lab11 implicit none real*4 A(100000), min, max integer*4 N, bin(50), binCount logical*1 ok binCount = 50 !-------------------------------------------------------------------- call GetData(A, N, min, max, ok) if (.NOT. ok) then print*, "Invalid entries! Program aborted." else call Group(A, N, bin, binCount, min, max) call ShowData(N, bin, binCount, min, max) end if !-------------------------------------------------------------------- end
The subroutine GetData
has the following header:
subroutine GetData(A, N, min, max, ok) implicit none integer*4 N real*4 A(100000), MyRandom, avg, std, min, max logical*1 ok
It prompts the user to enter the number of numbers
to generate (N), their range (min and max), distribution type (1 for
uniform or 2 for normal),
and for type=2, the average and standard deviation. It validates the
entries to ensure N is positive and not greater than 100,000, and
that min is less than max. It then uses the MyRandom
function (below) to generate the desired numbers and place them in
array A and return.
The function MyRandom
has the following header:
real*4 Function MyRandom(min, max, avg, std, type) implicit none real*4 min, max, avg, std, x, rand integer*4 typeIt returns one real*4 random number in the specified range having the specified distribution type. The SLATEC library has routines for both uniformly ad normally distributed numbers. Once a number x is generated it should clipped and returned. Clipping is needed in order to satisfy the min / max requirement as follows:
if (x .LT. min) then x = min else if (x .GE. max) then x = max - 0.000001 end if
Subroutine Group
receives N
elements in A
and it
must populate the binCount
elements of array bin
by counting how
many of the elements of A
fall in each of its intervals. bin(1)
contains a count of the elements in A
that are grater or equal to
min
and less than min+width
, where width =(max-min)/binCount
is the width of each bin. Similarly, bin(2)
contains a count of the elements in A
that are grater or equal to
min+width
but less than min+2*width
, and so on.
The subroutine must start by initializing all elements in array bin
to zero
(since they are counters) and then scan the array A
once. When one of its
elements, i
, is visited, a decision has to be made as to which interval it
belongs
to, and hence, which element of bin
should be incremented.
Subroutine ShowData generates the chart and has the following header:
subroutine ShowData(N, bin, binCount, min, max) implicit none integer*4 N, binCount, bin(binCount) real*4 min, maxIt creates a 2-dimensional array of 100 rows and 50 columns with each element being a character*1; e.g.
character*1 chart(0:100, 0:50)where coloumn zero corresponds to the y-axis (where a vertical bar, or pipe is displayed), and row zero corresponds to the first row above the x-axis. The columns correspond to the bins and the rows to the percents. We adopt the convention that a percent greater or equal to zero and less than 1 is mapped to row#0, and so on. A percent equal to 100% (or 1) is mapped to row#100.
Initialize the array so that all elements are blanks except all elements at column zero have a pipe character. Determine the highest percentage so that you can restrict the y-axis to the data. To print row #i, use a statement like:
print*, (chart(i,j), j=0, binCount)Add formatting as needed.
To check this lab, generate a listing of the source code of your completed system together with a number of test cases. You can re-direct the output of ShowData to a disk file.