Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在gfortran中刷新到零_Fortran_Gfortran_Underflow - Fatal编程技术网

在gfortran中刷新到零

在gfortran中刷新到零,fortran,gfortran,underflow,Fortran,Gfortran,Underflow,是否有办法强制gfortran中的底流冲洗为零 我不敢相信这是第一次有人问这个问题,但我在任何地方都找不到任何东西。如果这是重复的,那就是罪过。您可以通过支持Fortran 2003 IEEE模块的gfortran最新版本来实现这一点。该标准定义了两种底流模式——渐变模式和突变模式。“突然”是您想要的一个,它将下溢设置为0并发出下溢浮点异常信号。您可以使用功能ieee\u support\u underflow\u control(X)测试是否支持控制下溢模式,该功能测试实X is类型的下溢控制

是否有办法强制gfortran中的底流冲洗为零


我不敢相信这是第一次有人问这个问题,但我在任何地方都找不到任何东西。如果这是重复的,那就是罪过。

您可以通过支持Fortran 2003 IEEE模块的gfortran最新版本来实现这一点。该标准定义了两种底流模式——渐变模式和突变模式。“突然”是您想要的一个,它将下溢设置为0并发出下溢浮点异常信号。您可以使用功能
ieee\u support\u underflow\u control(X)
测试是否支持控制下溢模式,该功能测试实X is类型的下溢控制,如果支持,则返回逻辑true。如果支持,则可以调用ieee_set_underflow_mode(.false.)来设置突然下溢模式

以下是一个测试程序,可用于测试默认真实类型的下溢控制支持:

program test
  use, intrinsic :: ieee_arithmetic
  use, intrinsic :: iso_fortran_env, only: compiler_version, compiler_options
  implicit none
  logical :: underflow_support, gradual, underflow
  real :: fptest
  integer :: i

  print '(4a)',  'This file was compiled by ', &
       compiler_version(), ' using the options ', &
       compiler_options()
  fptest = 0.0
  underflow_support = ieee_support_underflow_control(fptest)
  if (underflow_support) then
     print *,'Underflow control supported for the default real kind'
  else
     stop 'no underflow control support'
  end if

  call ieee_set_underflow_mode(.false.)
  call ieee_get_underflow_mode(gradual)
  if (.not.gradual) then 
     print *,'Able to set abrupt underflow mode'
  else
     stop 'error setting underflow mode'
  end if

  fptest = 2e-36
  do i=1,50 ! 50 iterations max
     fptest = fptest * 0.5
     print '(e15.10)',fptest
     call ieee_get_flag(ieee_underflow,underflow)
     if (underflow) print *,'Underflow exception signaling'
     if (fptest == 0.0) exit
  end do

end program test
使用gfortran 5.2.0版,该程序输出:

This file was compiled by GCC version 5.2.0 using the options -mtune=generic -march=x86-64 -fno-unsafe-math-optimizations -frounding-math -fsignaling-nans
 Underflow control supported for the default real kind
 Able to set abrubpt underflow mode
.1000000036E-35
.5000000180E-36
.2500000090E-36
.1250000045E-36
.6250000225E-37
.3125000112E-37
.1562500056E-37
.0000000000E+00
 Underflow exception signaling
gfortran 5.2文档建议在使用IEEE模块时随时使用编译器选项标志
-fno不安全的数学优化-fronting math-fsignaling nans
,以确保遵守标准。

一种“刷新到零”的惰性方法是使用gfortran的
-funsafe数学优化来:

允许可能违反IEEE或ISO标准的数学优化

或在:

此模式启用了允许任意重新关联和转换的优化,而不保证准确性。它也不试图保留零的符号

例如,
small.f

      program test
        real r
        r=1e-40
        print *,'r on next line'
        print *,r
      end program
在没有任何标志的情况下,将显示非零非规范(小)数字,无错误:

$ gfortran -g small.f
$ ./a.out
 r on next line
   9.99994610E-41
捕获非规范化数字,该数字在尝试打印值时崩溃:

$ gfortran -g -ffpe-trap=denorm small.f
$ ./a.out
 r on next line

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.

Backtrace for this error:
#0  0x2aaaab05c26f in ???
#1  0x2aaaaac61aed in get_float_string
        at ../../../libgfortran/io/write_float.def:1064
#2  0x2aaaaac6423d in list_formatted_write_scalar
        at ../../../libgfortran/io/write.c:1889
#3  0x4008f1 in test
        at /path/to/small.f:5
#4  0x400941 in main
        at /path/to/small.f:6
Floating point exception
并添加了将其刷新为零的标志:

$ gfortran -g -ffpe-trap=denorm -funsafe-math-optimizations small.f
$ ./a.out
 r on next line
   0.00000000

请使用通用版本,没有多少人使用单独的版本,并且您的问题根本不是针对Fortran版本的。此处讨论的主题:非常完整的答案。非常感谢。