【问题标题】:Floating point cast results in arithmetic exception in Fortran浮点转换导致 Fortran 中的算术异常
【发布时间】:2018-02-14 10:11:41
【问题描述】:

以下代码传递了一个 64 位浮点数(双精度),并在将该值传递给 API 之前将其缩减为 32 位单精度。

  real*8 z
  real*4 z1
  z1 = real(z)

在 z 的某些值上,我们得到一个例外;

收到 SIGFPE:发生算术异常

我使用调试器输出 z 中的值,结果是 -1.1889755140229473e+044,所以这显然是问题所在。

我认为real(z) 会将此值截断为单精度,但不会出错。 如何将这个 64 位双精度无异常转换为 32 位单精度?

这是来自以前在 Silverfrost Fortran 32 位下编译的现有代码库,现在是 gfortran 64 位。将整个调用堆栈转换为单精度来解决它可能是不可能的。

【问题讨论】:

  • 你能提供z的具体有问题的值吗?
  • 请参阅en.wikipedia.org/wiki/Single-precision_floating-point_format 了解最大 32 位浮点值(绝对值 ≈ 3.402823e+38),并查看有关处理浮点溢出的编译器文档。
  • @PierredeBuyl 上面提到了一个值 (-1.1889755140229473e+044)。
  • 演员本身只是用 gfortran(4、5 和 7、64 位 linux 系统)返回“Infinity”
  • @PierredeBuyl 有同样的问题,但在消息中:“z 原来是 -1.1889755140229473e+044”

标签: fortran gfortran


【解决方案1】:

作为答案发布,因为我相信我可以确定问题。

gfortran 针对浮点异常的行为取决于标志 -ffpe-trap。虽然您没有自己设置,但它可能会在您的特定平台上启用。

使用以下程序

      real(kind=8) z
      real(kind=4) z1
      z = -1.1889755140229473d+034
      z = z*1d10
      z1 = real(z)
      write(*,*) z, z1
      end

编译时出现运行时异常

 gfortran -ffpe-trap=overflow -o scast scast.f90

程序只是输出

  -1.1889755140229473E+044        -Infinity

当我省略标志 -ffpe-trap=overflow.

要真正解决您的问题,您必须决定在发生溢出时该怎么做。除非您通过某种机制实际控制溢出行为, 异常的发生是存在问题的有用提示。

最后,正如 Ian Bush 所提到的,您应该利用当前的过渡来使用符合标准的声明。有关此问题的简短介绍,请参阅 Steve Lionel 的 blog post

【讨论】:

  • 也许使用模块 iso_fortran_env 并将 kind=8 替换为 kind=REAL64kind=4 替换为 kind=REAL32。 kind 值取决于编译器。
【解决方案2】:

假设 IEEE 32 和 64 位实数,单精度可表示的最大模数约为 ±3.40282×10**38 。你的数字比这个大,所以转换为单精度会抛出异常。

另外请注意 real*8 和类似的不是也从未成为 Fortran 的一部分。请了解 Fortran 种类机制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-25
    • 2010-09-10
    • 2018-11-14
    • 2016-06-30
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多