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 中是不是有更好的双精度赋值?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 PHP 中的双精度数组中计算第 n 个百分位数?

在 Fortran 90 中使用二维数组与派生类型数组

Inferschema 检测列作为字符串而不是来自 pyspark 中镶木地板的双精度

打印带有 2 位小数的双精度值和 .不是,[重复]

使用intel内在函数加载内存中等距的双精度数?

在 Fortran90 中从文本文件中跳过一行