Fortran 90 中是不是有更好的双精度赋值?
Posted
技术标签:
【中文标题】Fortran 90 中是不是有更好的双精度赋值?【英文标题】:Is There a Better Double-Precision Assignment in Fortran 90?Fortran 90 中是否有更好的双精度赋值? 【发布时间】:2011-09-03 00:17:13 【问题描述】:在 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
我得到了结果:
Single precision: 0.123456791043282
Double precision: 0.123456791043282
Double precision (DBLE): 0.123456791043282
Double precision (_dp): 0.123456789012346
单精度结果按预期从第 8 位小数开始四舍五入,但只有我用 _dp 显式分配的双精度变量保持所有 16 位精度。这似乎很奇怪,正如我所期望的(我对 Fortran 比较陌生)双精度变量将自动是双精度的。有没有更好的方法来分配双精度变量,还是我必须像上面那样显式键入它们?
【问题讨论】:
注意变量e
的初始化是用一个整型常量完成的; 0_dp
是类型号为 dp 的整数类型。不幸的是,在许多编译器上,实数和整数的种类数重叠,所以你不会因为这个错误而得到编译时错误(我认为这是无意的)。
【参考方案1】:
未标记为双精度的实数将被假定为单精度。仅仅因为稍后您将其分配给双精度变量,或将其转换为双精度,这并不意味着该值将“神奇地”成为双精度。它不会向前看如何使用该值。
【讨论】:
所以你的意思是我将值分配给双精度“容器”这一事实并不重要,除非我明确说它是一个双精度值? 正确。正如我所说,它不会提前看到稍后将如何使用该值。它看到一个真实的文字,它没有被标记为双精度,因此它假定它是单精度的。 @tomshafer:清楚地了解赋值语句的评估方式很重要。首先,根据优先规则对 RHS 进行全面评估;在每一步,如果是混合模式表达式,则执行所需的隐式类型转换。只有在完全评估 RHS 之后,才会将结果分配给 LHS,如果需要,再进行隐式类型转换。 谢谢大家,这更有意义。【参考方案2】:此处链接了几个问题,因此最好通过示例更明确地说明一些细节,尤其是对于初学者。
正如 MRAB 在他的正确答案中所说,表达式总是在没有任何上下文的情况下进行评估,所以
0.12345678901234567890
是一个默认(单)精度浮动文字,无论它出现在哪里。指数形式的浮点数也是如此
0.12345678901234567890E0
它也是一个默认的精度数。
如果要使用双精度常量,可以使用D
代替上述形式的E
。即使将这样的双精度常量分配给默认精度变量,它也会首先被视为双精度数,然后再转换为默认精度。
您在问题中使用的方式(使用种类符号和几个种类常量)更通用、更现代,但原理是相同的。
0.12345678901234567890_sp
是一种sp
和
0.12345678901234567890_dp
是一个数字dp
,它们出现在哪里并不重要。
正如您的示例所示,这不仅与分配有关。在行中
c = DBLE(0.12345678901234567890)
首先数字0.12345678901234567890
是默认精度。然后由DBLE
将其转换为双精度,但这是在一些数字已经丢失之后完成的。然后将这个新的双精度数分配给c
。
【讨论】:
这个问题是许多类似问题的重复目标,这个额外的解释很有用。以上是关于Fortran 90 中是不是有更好的双精度赋值?的主要内容,如果未能解决你的问题,请参考以下文章