是否可以使用NaN设置参数变量,并将其用于特定模块。我想将其用于初始化其他变量。因此,如果它们未更新,我将面临运行时错误,而不是使用某些随机数进行模拟。
我正在使用GFortran。
是否可以使用NaN设置参数变量,并将其用于特定模块。我想将其用于初始化其他变量。因此,如果它们未更新,我将面临运行时错误,而不是使用某些随机数进行模拟。
我正在使用GFortran。
除了 Vladimir F's answer提到的内容,我要补充一点,gfortran 5.0(但不包括早期版本)支持IEEE内置模块。
与其这样做,
real x
x=0
x=0/x
可以使用
use, intrinsic :: iso_fortran_env
use, intrinsic :: ieee_arithmetic
integer(int32) i
real(real32) x
x = ieee_value(x, ieee_quiet_nan)
i = transfer(x,i)
ieee_signaling_nan
可能并不真正给您那个。]ieee_value()
不能直接用于初始化:对它的引用不是常量表达式。对于这种用途,采用此方法获取位模式并应用其他答案的方法。ieee_signaling_nan
会产生这种情况(虽然建议这样做)。我不知道gfortran返回什么-如果您可以测试,请告诉我。在某种意义上,一个安静的NaN仍然很有价值:你知道出了问题。对于调试来说不太方便。 - francescalus这是可能的。首先,您需要找出哪个位模式表示可能的NaN值之一。您可以将位模式存储在整数中:
use, intrinsic :: iso_fortran_env
real(real64) x
integer(int64) i
x = 0
x = 0/x
print *, x
print *, transfer(x, i)
end
它会给出:-2251799813685248
然后,您可以使用以下方式初始化变量:
real(real64), parameter :: nan64 = transfer(-2251799813685248_int64, 1._real64)
real(real32), parameter :: nan32 = transfer(-4194304_int32, 1._real32)
use, intrinsic :: iso_fortran_env
use ieee_arithmetic
real(real32), parameter :: qnan = transfer(int(B'01111111110000000000000000000000',int32), 1._real32)
real(real32), parameter :: snan = transfer(int(B'01111111101000000000000000000000',int32), 1._real32)
if (IEEE_SUPPORT_DATATYPE(qnan)) then
print *, "qnan:", (ieee_class(qnan)==ieee_quiet_nan)
end if
if (IEEE_SUPPORT_DATATYPE(snan)) then
print *, "snan:", (ieee_class(snan)==ieee_signaling_nan)
end if
end
返回
qnan: T
snan: T
在默认设置下,Intel Fortran中的NaN信号是启用的。在GCC(gfortran)中,默认情况下禁用了NaN信号,并且可以通过-fsignaling-nans
启用,但似乎并没有帮助。
其他位,包括第一个符号位,通常被忽略。
-finit-real=nan
。手动执行此操作可以使您更加精细地控制。可以参考francescalus的答案,该答案使用了标准函数。不幸的是,它不适用于参数常量,但仍然有用。
ieee_value
的结果不能分配给parameter
。另一种方法是使用一个protected
模块变量代替parameter
。但是,这样需要在程序开始时调用模型初始化函数。请注意保留HTML标记。module nan_module
implicit none
real, protected :: nan_real
contains
subroutine init_nan_module
use, intrinsic :: ieee_arithmetic
implicit none
nan_real = ieee_value(nan_real, ieee_quiet_nan)
end subroutine
end module nan_module
program test
use nan_module, only: init_nan_module, nan_real
implicit none
real :: x
call init_nan_module()
x = nan_real
write(*,*) x, 'isnan', isnan(x)
end program test
is.nan
):real(kind = c_double), parameter :: ONE = 1_c_double
real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', ONE)
有趣的是,real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1_c_double)
未通过我的 is.nan
检查。
1_c_double
是一个整数吗?意识到这一点后,你可能就不会再觉得失败有多有趣了。你的第一行可以只是real(kind = c_double), parameter :: ONE = 1
,它会做同样的事情。请参见我的答案以获取实数的正确语法。 - Vladimir F Героям славаreal(c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1._c_double)
或 real(c_double), parameter :: NAN = TRANSFER(9218868437227405313_c_int64_t, 1._c_double)
。 - Vladimir F Героям слава
-finit-real=nan
选项。 - francescalus-init=arrays -init=snan
。 - knia