Fortran 90中有更好的双精度分配吗?

tom*_*fer 6 fortran fortran90

在Fortran 90中(在Mac OS X上使用gfortran)如果我将一个值赋值给一个双精度变量而没有明确地添加一种类型,则精度不会"采用".我的意思是,如果我运行以下程序:

program sample_dp

implicit none

integer, parameter :: sp = kind(1.0)
integer, parameter :: dp = kind(1.0d0)

real(sp) :: a = 0.
real(dp) :: b = 0., c = 0., d = 0.0_dp, e = 0_dp

! assign values
a = 0.12345678901234567890
b = 0.12345678901234567890
c = DBLE(0.12345678901234567890)
d = 0.12345678901234567890_dp

write(*,101) a, b, c, d
101 format(1x, 'Single precision: ',  T27, F17.15, / &
           1x, 'Double precisison: ', T27, F17.15, / &
           1x, 'Double precision (DBLE): ', T27, F17.15, / &
           1x, 'Double precision (_dp): ',  T27, F17.15)

end program
Run Code Online (Sandbox Code Playgroud)

我得到了结果:

Single precision:        0.123456791043282
Double precision:        0.123456791043282
Double precision (DBLE): 0.123456791043282
Double precision (_dp):  0.123456789012346
Run Code Online (Sandbox Code Playgroud)

单精度结果按预期在第8个小数处开始四舍五入,但只有我用_dp明确指定的双精度变量保持所有16位精度.这看起来很奇怪,正如我所料(我对Fortran相对较新),双精度变量会自动为双精度.是否有更好的方法来分配双精度变量,或者我必须如上所述明确键入它们?

MRA*_*RAB 8

未标记为双精度的实数将被假定为单精度.只是因为稍后您将其分配给双精度变量,或将其转换为双精度,这并不意味着该值将"神奇地"为双精度.它没有展望未来如何使用该值.

  • @tomshafer:重要的是要清楚地了解赋值语句的评估方式.首先,根据优先规则对RHS进行全面评估; 在每个步骤中,如果它是混合模式表达式,则执行所需的隐式类型转换.只有在完全评估RHS后,才会将结果分配给LHS,如果需要,再次使用隐式类型转换. (7认同)
  • 正确.正如我所说,它没有展望未来如何使用该值.它看到一个真正的文字,它没有标记为双精度,因此它假定它是单精度. (2认同)

Vla*_*r F 7

这里有几个问题链接,所以最好用例子更明确地说明一些细节,特别是对于初学者。

正如 MRAB 在其正确答案中所述,表达式总是在没有任何上下文的情况下进行计算,因此

 0.12345678901234567890
Run Code Online (Sandbox Code Playgroud)

是默认(单)精度浮点文字,无论它出现在哪里。这同样适用于指数形式的浮点数

 0.12345678901234567890E0
Run Code Online (Sandbox Code Playgroud)

它也是一个默认的精度数。

如果要使用双精度常量,可以使用上面的形式D代替E。即使将这样的双精度常量分配给默认精度变量,它也会首先被视为双精度数,然后将其转换为默认精度。

您在问题中使用的方式(使用种类符号和几个种类常数)更通用且更现代,但原理是相同的。

 0.12345678901234567890_sp
Run Code Online (Sandbox Code Playgroud)

是一些种类sp

 0.12345678901234567890_dp
Run Code Online (Sandbox Code Playgroud)

是多种类型dp,它们出现在何处并不重要。

正如您的示例所示,这不仅与分配有关。在行中

 c = DBLE(0.12345678901234567890)
Run Code Online (Sandbox Code Playgroud)

首先数字0.12345678901234567890是默认精度。然后它被转换为双精度DBLE,但这是在一些数字已经丢失之后完成的。然后将这个新的双精度数分配给c