【问题标题】:Maximum value of 64 bit floating point number for overflow detection溢出检测的 64 位浮点数的最大值
【发布时间】:2020-03-29 14:49:48
【问题描述】:

我有一个看似简单的问题:我想通过执行以下操作来检测 Fortran 中的浮点加法是否会溢出:

real*8 :: a, b, c

a = ! some value
b = ! some value

if (b > DOUBLE_MAX - a) then
  ! handle overflow
else
  c = a + b

问题是我不知道DOUBLE_MAX 应该是什么。我知道浮点数是如何根据 IEEE 754 表示的,但双精度浮点数可表示的最大值对于 real*8 类型的变量似乎太大了(即,如果我尝试分配 1.7976931348623157e+308对这样一个变量 gfortran 抱怨)。 C 和 C++ 为此目的预定义了常量/通用函数,但我找不到 Fortran 等价物。

注意:我知道real*8 不是真正标准的一部分,但似乎没有其他方法可以可靠地指定浮点数应使用双精度格式。

【问题讨论】:

  • 我在这里找了一个副本但没有找到,虽然我希望能找到一个。不幸的是,有很多帖子包括“巨大”作为短语。请随意将其指向重复项,我将删除我的答案。
  • “似乎没有其他方法可以可靠地指定浮点数应使用双精度” 有多种方法,但 real*8 不是其中之一他们。它指定了一个具有 8 字节存储大小的实数,而不是我所知道的任何含义的双精度。 Fortran 双精度使用double precision 或设置为kind(1.0_dp) 的种类常量。如果你想要IEEE双精度浮点类型,使用IEEE模块,不要使用real*8,那什么都保证。
  • Strictly real*8 根本不指定和保证任何内容,它甚至可能无法编译,而不是 Fortran。看看stackoverflow.com/questions/838310/fortran-90-kind-parameter 看看你应该怎么做,请把这个古老的扩展扔进垃圾箱。
  • 您可能还想看看标准 Fortran 处理浮点异常的方式

标签: fortran gfortran fortran95


【解决方案1】:

这样的?

real(REAL64) function func( a, b )
  use, intrinsic :: iso_fortran_env, only: REAL64, INT64
  use, intrinsic :: ieee_arithmetic, only: ieee_value, ieee_set_flag, IEEE_OVERFLOW, IEEE_QUIET_NAN
  implicit none
  real(REAL64), intent(in) :: a, b
  real(REAL64), parameter  :: MAX64 = huge(0.0_REAL64)

  if ( b > MAX64-a ) then
    ! Set IEEE_OVERFLOW flag and return NaN
    call ieee_set_flag(IEEE_OVERFLOW,.true.)
    func = ieee_value(func,IEEE_QUIET_NAN)
  else
    func = a + b
  end if

  return
end function func

我能找到的所有内在 ieee_exceptions 模块是:
https://github.com/gcc-mirror/gcc/blob/master/libgfortran/ieee/ieee_exceptions.F90

有关设置 NaN 值,请参阅post

【讨论】:

  • ieee_value (如链接中所示)是设置 NAN 值的更简洁的方法。另外我想我会做加法然后测试溢出而不是写的,感觉好像我对浮点实现的假设更少。
  • @Ian Bush 确实是更清洁的方式。我改成ieee_value...
  • 简洁,但 REAL64 不是只能从 Fortran 2003 获得吗?
  • Nvm,这至少似乎是用 Fortran 95 编译器编译的,所以我会接受这是做我想做的事情的正确方法。还有@IanBush:您建议使用ieee_get_flag 检查溢出,对吗?这似乎更合理。
  • 是的 - 我会添加并使用 ieee_get_flag (并确保暂停模式)。我也可能会使用 ieee_selected_real_kind 。而这一切都是 Fortran 2003,这是你现在应该使用的标准
【解决方案2】:

可能有更好的方法来检测溢出,但您问题的准确答案是使用huge 函数。 HUGE(a) 返回a 类型可表示的最大可能数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    相关资源
    最近更新 更多