以下代码传递64位浮点(double),并在将该值传递给API之前将其减少为32位。
real*8 z
real*4 z1
z1 = real(z)
在某些z值上,我们得到了一个例外;
收到SIGFPE:发生算术异常
我使用调试器输出z中的值,结果是-1.1889755140229473e + 044,这显然是问题所在。
我认为real(z)
会将此值截断为单精度,但不会出现错误。 如何将此64位双精度转换为32位单,无异常?
这是来自以前在Silverfrost Fortran 32位下编译的现有代码库,现在是64位的gfortran。将整个调用堆栈转换为单精度以解决它可能是不可能的。
答案 0 :(得分:2)
作为答案发布,因为我相信我可以发现问题。
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
时。
要真正解决您的问题,您必须决定发生溢出时该怎么做。除非您通过某种机制实际控制溢出行为, 异常的发生是一个有用的提示,即存在问题。
最后,正如伊恩布什所提到的,你应该利用当前的过渡来使用符合标准的声明。请参阅Steve Lionel的blog post,了解此问题的简短介绍。
答案 1 :(得分:1)
假设IEEE 32和64位实数,单个精度中可表示的最大模数值约为±3.40282×10 ** 38。你的数字大于此数,因此转换为单精度会引发异常。
另请注意真实的* 8和类似的不是,也从未成为Fortran的一部分。请了解Fortran类型机制。