使用双精度幻数时的最佳实践

时间:2017-07-18 00:52:46

标签: fortran

我是否必须在所有magic numbers(文字常量)的末尾指定D(例如1.234D+00),如果我已经宣布所有的双精度?

1 个答案:

答案 0 :(得分:8)

简短回答:是的,你做到了。

长答案:默认情况下,除非另有说明,否则真实文字是单精度。将单精度文字分配给双精度变量会导致精度损失;也就是说,单精度文字首先作为单精度计算,然后分配给更高精度的变量。我懒得从另一个房间检索F2003手册,但我怀疑单对双分配将低有效尾数位设置为零。无论是那个还是由供应商决定的。

无论如何,这里展示了当你在文字和变量之间混合精度时会发生什么(注意0.1不能在二进制浮点中干净地存储):

!> 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

结果如下:

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 

您会看到在所有文字都是单精度的情况下(包括那些没有明确精确设置的文字),双精度变量中存储的重要性“噪音”很低。

我觉得有趣的是,混合精度文字的操作似乎在执行操作之前将所有文字提升到更高的精度。有更多语言规范的人可能能够解释这一点。

我的建议:如有疑问,请明确。它更安全,我认为值得额外的击键。