Best practice when dealing with double precision magic numbers

Do I have to put D

(for example 1.234D+00

) at the end of all magic numbers (literal constants) if I have already declared all double precision?

+1


source to share


1 answer


Short answer: Yes, you do.

Long answer: By default, real literals are single precision unless otherwise noted. Assigning single precision literals to double precision variables results in a loss of precision; that is, single precision literals are first evaluated as single precision and then assigned to a higher precision variable. I'm too lazy to get the F2003 reference from another room, but I suspect a single assignment sets the minimum value bit of the mantissa to zero. Either that or it's left up to the supplier.

No matter what happens when you mix precision between literals and variables (note that 0.1 cannot be stored purely in binary floating point):

!> Demonstrate the effects of D and E suffixes on precision of literals
program whatkind
    use iso_fortran_env, only: output_unit, REAL32, REAL64
    implicit none

    real (kind=REAL64) :: dtest

10 format('Literal ', A, ' is of kind ', I2)
20 format(/, A)
30 format(/, 'Value stored in ', A, ' precision generated with ', A,    &
          ' precision literals:')
40 format('Literal is ', A)

    continue

    write(output_unit, 10) '1.0', kind(1.0)
    write(output_unit, 10) '1.0E0', kind(1.0E0)
    write(output_unit, 10) '1.0D0', kind(1.0D0)
    write(output_unit, 10) '1.0_REAL32', kind(1.0_REAL32)
    write(output_unit, 10) '1.0_REAL64', kind(1.0_REAL64)

    write(output_unit, 20) 'Raw tenths tests:'

    dtest = 0.1
    write(output_unit, 30) 'double', 'single'
    write(output_unit, 40) '0.1'
    write(output_unit, *) dtest

    dtest = 0.1D0
    write(output_unit, 30) 'double', 'double'
    write(output_unit, 40) '0.1D0'
    write(output_unit, *) dtest

    dtest = 1.0 / 10.0
    write(output_unit, 30) 'double', 'single'
    write(output_unit, 40) '0.1'
    write(output_unit, 40) '1.0 / 10.0'
    write(output_unit, *) dtest

    dtest = 1.0_REAL64 / 10.0_REAL64
    write(output_unit, 30) 'double', 'double'
    write(output_unit, 40) '1.0_REAL64 / 10.0_REAL64'
    write(output_unit, *) dtest

    dtest = 1.0_REAL32 / 10.0_REAL32
    write(output_unit, 30) 'double', 'single'
    write(output_unit, 40) '1.0_REAL32 / 10.0_REAL32'
    write(output_unit, *) dtest

    dtest = 1.0_REAL64 / 10.0_REAL32
    write(output_unit, 30) 'double', 'mixed'
    write(output_unit, 40) '1.0_REAL64 / 10.0_REAL32'
    write(output_unit, *) dtest

    dtest = 1.0_REAL32 / 10.0_REAL64
    write(output_unit, 30) 'double', 'mixed'
    write(output_unit, 40) '1.0_REAL32 / 10.0_REAL64'
    write(output_unit, *) dtest

end program whatkind

      

The results of this:



Literal 1.0 is of kind  4
Literal 1.0E0 is of kind  4
Literal 1.0D0 is of kind  8
Literal 1.0_REAL32 is of kind  4
Literal 1.0_REAL64 is of kind  8

Raw tenths tests:

Value stored in double precision generated with single precision literals:
Literal is 0.1
  0.10000000149011612     

Value stored in double precision generated with double precision literals:
Literal is 0.1D0
  0.10000000000000001     

Value stored in double precision generated with single precision literals:
Literal is 0.1
Literal is 1.0 / 10.0
  0.10000000149011612     

Value stored in double precision generated with double precision literals:
Literal is 1.0_REAL64 / 10.0_REAL64
  0.10000000000000001     

Value stored in double precision generated with single precision literals:
Literal is 1.0_REAL32 / 10.0_REAL32
  0.10000000149011612     

Value stored in double precision generated with mixed precision literals:
Literal is 1.0_REAL64 / 10.0_REAL32
  0.10000000000000001     

Value stored in double precision generated with mixed precision literals:
Literal is 1.0_REAL32 / 10.0_REAL64
  0.10000000000000001 

      

You can see how in cases where all literals have the same precision (including those that have no explicit precision), the double-precision variable is kept low in noise.

I'm wondering that mixed-precision literal operations seem to push all literals to a higher precision before performing the operation. Someone with more spec-fu language can explain this.

My advice: when in doubt, be clear. It's safer and I think it's worth the extra keystrokes.

+7


source







All Articles