• No se han encontrado resultados

Parte III: Fundamentación Metodológica

4.2 Instrumentos

4.2.1 Observación participante

4.2.1.1 Diario de campo

MOD(A,P) = A–P*INT((A/P)

The final two functions listed above, NINT and SIGN, have real or integer arguments and the result is of the same type as the arguments.

DBLE and DPROD

There are two intrinsic functions to do with “double precision” real data. DBLE(A) is like REAL (A) but the result is of double precision type. DPROD(X, Y) calculates the double-precision-real product of the default-real arguments X

Fortran 95 features not in Fortran 90

The CEILING and FLOOR functions may also have a KIND argument (as INT and NINT may) to give a result of the specified KIND of integer.

The SIGN function may be used for a special purpose if the processor is configured (as some are) to offer a distinction between real variables of positive and negative zero values.

If the second argument of SIGN is a variable or expression of zero value, the value of SIGN may be positive or negative. This facility is provided in Fortran 95 because some processors, following an IEEE standard, have one bit pattern for positive zero and another for negative zero.

5.4

Numeric inquiry functions

The precision of real number arithmetic, and the maximum and minimum sizes of real numbers, depend on the processor. To monitor and manage precision Fortran provides a number of utility functions. The functions available include:

HUGE(X) The largest representable number

PRECISION (X) An integer equal to the maximum decimal precision, i.e. the maximum number of significant figures

TINY(X) The smallest representable non-zero positive number

RANGE (X) An integer equal to the order of magnitude of the largest representable number or, if greater, of the inverse of the smallest. So, RANGE (X) is equal to the greater of INT (LOG10 (HUGE(X)) and INT(–LOG10 (TINY(X)))

EPSILON(X) A positive real number almost negligible in comparison with unity, convenient when you simply want to use as small a number as the processor will support (e.g. for numerical differentiation).

Different kinds of real number are distinguished by the KIND parameter, which was introduced in Chapter 3. It is a parameter that may be specified in a type declaration statement and it must have a non-negative integer value. When a real constant appears, the KIND parameter may follow the value after an underscore, as in

–78.915443_normal 1877724. _quad 4.65E–9_hiprec

where normal, quad and hiprec are named constants given previously in type declaration statements (with the PARAMETER attribute, Chapter 8) and having values corresponding to KIND parameters valid for this processor.

The KIND parameter could alternatively be given explicitly, as in –78.915443_2

but this sort of code is unsafe as it may not be portable between processors: the actual values of the KIND parameters (2 in this instance) are not laid down in Fortran. The best thing to do is to use a special intrinsic function, KIND(x), which returns the value of the KIND parameter for the number X. The default KIND parameter is given by, say, KIND(0.0). Real numbers of higher precision can always be specified by a KIND parameter as defined by, say,

INTEGER, PARAMETER :: hiprec = KIND(0.0D0)

where 0.0D0 is a “double precision” number, as mentioned in Section 3.7. Notice that the word KIND can be used in three different ways: as a parameter when real data is declared, as an argument keyword in several intrinsic functions, and as the name of a particular intrinsic function. Examples of the three sorts of use are the statements

REAL (KIND=hiprec) :: sensitivity

q = REAL(A=k, KIND=2) – AINT(A=1.0, KIND=2) IF (KIND(r).NE.2) THEN

Another example will be given at the end of this section. In addition to KIND, there is another intrinsic function provided to help control the use of real numbers of different kinds. It is the function SELECTED_REAL_KIND(P, R), which returns an integer equal to the minimum KIND value used by the processor for real numbers of a given precision and range. The argument P is the required decimal precision and R is the required exponent range, and it is not necessary for both arguments to be present.

SELECTED_REAL_KIND could be used in a type declaration statement (see Chapter 8) such as INTEGER, PARAMETER :: nreal = SELECTED_REAL_KIND(P=15)

which sets nreal to be a named integer constant equal to the KIND parameter necessary for 15-figure decimal precision. Variables requiring this precision can subsequently be declared by statements like

REAL (KIND=nreal) :: x, y, z

However, one should first check that nreal is positive, because the SELECTED_REAL_KIND function will return a negative value if the processor cannot attain the required precision or range. In any program doing serious number crunching it is advisable for the programmer to decide in advance what precision and range are going to be needed. You could have a statement such as

IF (SELECTED_REAL_KIND(P=15, R=80) &

/= SELECTED_REAL_KIND(0.0)) STOP to check that non-default kinds are not needed, or

IF (SELECTED_REAL_KIND(P=20, R=100)<0) STOP

to check that kinds of real numbers are available that will be capable of achieving the needed precision and range. (The STOP statement is mentioned in Section 6.7.)

Normally the default precision will be amply good enough for most calculations. Arguably, a program is badly designed if it relies on exceptionally high decimal precision. In the remainder of this book, little more will be said about non-default kinds of data.

Among the intrinsic functions discussed so far there have been the functions REAL and KIND. It is worth emphasizing yet again that these functions should not be confused with the keywords or parameters REAL and KIND that can occur in type declaration statements. The statement

REAL(KIND=KIND(0.0D0)) :: giga=REAL(2**30)

is really quite tricky because it uses the keyword REAL, meaning that the data object giga is to be of real type, and also the function REAL, which converts the integer 2**30 into a real number; and also there is the KIND function, which yields the parameter needed by this processor to specify a double-precision number such as 0. 0D0, and the KIND keyword that applies that parameter to giga!

5.5 Exercises 5.A 5.A

1

Write programs to read a number from the keyboard and calculate and display the value(s) of its

(i) secant

(ii) inverse hyperbolic sine (arcsinh) (iii) logarithm to the base 16

5.A 2

Write a program to input a sum of money, an interest rate and a time in years, and to calculate what the sum has grown to after that time if the interest is compounded monthly.

5.A 3

A straight line (chord) divides a circle into two unequal parts. Write a program to calculate the area of the smaller part, given the circle’s radius and the length of the chord.

5.A 4

Write code to find the number of the current month of the year (using DATE_AND_TIME) and output its name.

5.A 5

If x is a real variable, write a line of code to calculate the natural logarithm of the complex number whose real and imaginary parts are cosh(x) and sinh(x).

5.A 6

Write a program which will simulate the tossing of a coin (writing out head or tail) using the millisecond counter of DATE_AND_TIME to give an integer of practically random parity.

5.A 7

Write a program which will input a sequence of ten integers and calculate their average when the largest one and the smallest one are disregarded.

5.A 8

Write a program to find and write the order of magnitude of the number given by EPSILON on your processor. Also, find out if the square of this number is representable as distinct from zero.

5.A 9

The intrinsic function SIGN(A, B) gives the first argument the sign of the second. Write code to do the same job without using this function.

5.6

More intrinsic subroutines: SYSTEM_CLOCK, CPU_TIME, RANDOM and RANDOMSEED

Besides DATE_AND_TIME, described at the start of this chapter, there are two other intrinsic subroutines used for timekeeping, namely SYSTEM_CLOCK and (in Fortran

95) CPU_TIME.

SYSTEM_CLOCK has up to three arguments and is called by a statement of the form CALL SYSTEM_CLOCK (COUNT=i, COUNT_RATE=j, COUNT_MAX=k)

The arguments are scalar integers with the keywords COUNT, etc. as shown. The COUNT argument measures time in the processor’s own basic units or “clock counts”. It is the same as the COUNT argument in the DATE_AND_TIME subroutine. COUNT_RATE allows the programmer to connect values of COUNT with real elapsed time, COUNT_RATE being the number of counts per second. COUNT_MAX gives the maximum count after which the clock is reset to zero. If the processor does not possess a clock then COUNT_RATE and COUNT_MAX are returned as zero. SYSTEM_CLOCK could be used by statements like

CALL SYSTEM_CLOCK(COUNT_RATE=nsec) .

. .

IF (nsec>0) THEN

CALL SYSTEM_CLOCK(COUNT=n) milliseconds = 1000*n/nsec

END IF

Note that all three arguments of SYSTEM_CLOCK are optional, although obviously there is no point in calling it if none are present.

Fortran 95 feature not in Fortran 90

CPU_TIME is an intrinsic subroutine that has one argument, of real type, measuring the “processor time”

in seconds. The precise definition of processor time will in general be dependent on the processor. TIME is a scalar in standard Fortran 95, but a parallel processor could provide an enhanced version of CPU_TIME returning an array of processor times.

There is a very useful pair of intrinsic subroutines used for generating random numbers, RANDOM and RANDOMSEED. RANDOM has a single argument, of real type, which is returned to the program with a random value in the range between 0 and 1. It does not matter what value (if any) the argument had before

RANDOM is called. If it is an array variable, then an array of different random numbers will be returned.

So, if x is a real scalar variable, CALL RANDOM(x)

gives x a random value between 0. 0 and 1. 0 (to be precise, 0.0 ≤ x < 1.0). A more complex usage is the following:

REAL :: radvec(3) = 99.0 .

. .

DO WHILE (SUM(radvec**2)>1.0) CALL RANDOM(radvec)

END DO

The DO WHILE syntax is explained in the next chapter. This code finds a random point within the three-dimensional unit sphere. It does so by picking a point within a cubic volume and checking to see if it is also within the enclosed sphere. The coordinates are preset to a large value merely to satisfy the WHILE condition when the DO loop is first entered: subsequently the loop is repeated until a point within the sphere is found.

The subroutine RANDOMSEED is to do with the initializing of the random number generator that RANDOM will invoke. RANDOMSEED has three optional arguments, but no more than one may be present in a particular call, so we could have any of the following

Documento similar