Oracle® Developer Studio 12.5:数值计算指南

退出打印视图

更新时间: 2016 年 6 月
 
 

4.2 什么是异常?

很难对异常进行定义。 下面引用 W.Kahan 的话:

当尝试执行的原子算术运算没有生成可普遍接受的结果时,就产生了运算异常。原子和可接受的含义随时间和使用场合而异。(请参见 W. Kahan 编著的《Handling Arithmetic Exceptions》。)

例如,当某个程序尝试求负数的平方根时,会产生异常。这是无效运算异常的一个示例。在出现此类异常时,系统会以下列两种方式之一进行响应:

  • 如果该异常的陷阱处于禁用状态(缺省情况),系统将记录异常发生这一事实,并使用 IEEE 754 针对异常运算指定的缺省结果继续执行该程序。

  • 如果该异常的陷阱处于启用状态,系统将生成 SIGFPE 信号。如果程序安装了 SIGFPE 信号处理程序,系统会将控制转交给该处理程序;否则,该程序将中止。

IEEE 754 定义了五个基本类型的浮点异常:无效运算、除以零、溢出、下溢不精确。前三个(无效、除和溢出)有时统称为常见异常。这些异常一旦出现,很少可被忽略。ieee_handler(3m) 手册页介绍了一种仅适用于在出现常见异常时自陷的简便方法。 另外两种异常(下溢和不精确)更常见。实际上,大多数浮点运算都会导致不精确异常。这些异常通常(尽管不总是)可以安全地忽略。缺省情况下,Oracle Developer Studio 12.5 C、C++ 和 f77 编译器将禁用所有 IEEE 陷阱。f95 编译器在缺省情况下将对常见异常启用陷阱。可通过使用 f95 –ftrap=none 进行编译来恢复符合 754 标准。

表 31简要介绍了 IEEE 标准 754 中的信息。它描述了五个浮点异常,以及在出现这些异常时 IEEE 运算环境的缺省响应。

表 31  IEEE 浮点异常
IEEE
异常
出现异常的原因
示例
在陷阱被禁用时
出现的缺省结果
无效运算
对于将要执行的运算,某个操作数无效。
(在 x86 上,当浮点栈下溢或溢出时也会出现该异常,尽管这不符合 IEEE 标准。)
  • 0 × ∞

  • 0 / 0

  • ∞ / ∞

  • x REM 0

  • 负数平方根的操作数

  • 信号 NaN 操作数的任何运算

  • 无序比较(请参见注释 1)

  • 无效转换(请参见注释 2)

无噪声 NaN
除以零
针对有限操作数执行运算时生成精确的无穷大结果。
  • 对于有限的非零 x,x / 0

  • log(0)

带有正确符号的无穷大
溢出
正确舍入的结果将比可用目标格式表示的最大有限数大的多(即,超过指数范围)。
  • 双精度:

    • DBL_MAX + 1.0e294

    • exp(709.8)

  • 单精度:

    • (浮点)DBL_MAX

    • FLT_MAX + 1.0e32

    • expf(88.8)

取决于舍入模式 (RM),以及中间结果的符号。请参见表 4-1 的注释中的第 4 项。
下溢
精确结果或正确舍入的结果将比可用目标格式表示的最小正常数小的多(请参见注释 3)。
  • 双精度:

    • nextafter(min_normal,-·)

    • nextafter(min_subnormal,-·)

    • DBL_MIN §3.0

    • exp(-708.5)

  • 单精度:

    • (浮点)DBL_MIN

    • nextafterf(FLT_MIN, -·)

    • expf(-87.4)

低于正常值或零
不精确
有效运算的舍入结果不同于无限精确结果。(大多数浮点运算都产生该异常。)
  • 2.0 / 3.0

  • (浮点)1.12345678

  • log(1.1)

  • DBL_MAX + DBL_MAX,当没有溢出陷阱时

该运算的结果(舍入、溢出或下溢)

4.2.1 表 4-1 的注释

  1. 无序比较:对于任何浮点值对来说,即使它们的格式不同,也可以对它们进行比较。可能有四种互斥关系:小于、大于、等于或无序。无序意味着至少有一个操作数为 NaN(not a number,非数)。

    每个 NaN 可与任何值(包括它本身)进行“无序”比较。 下表显示在关系为无序时,由哪一种谓词导致无效运算异常。

    数学谓词
    C、C++ 谓词
    Fortran 谓词
    无效表达式(如果无序的话)
    =
    ==
    .EQ.
    no
    !=
    .NE.
    no
    >
    >
    .GT.
    yes
    >=
    .GE.
    yes
    <
    <
    .LT.
    yes
    <=
    .LE.
    yes
  2. 无效转换:尝试将 NaN 或无穷大转换为整数,或者在从浮点格式转换时出现整数溢出。

  3. IEEE 单精度、双精度和扩展格式能表示的最小正规数分别为 2-126、2-1022 和 2-16382。有关 IEEE 浮点格式的说明,请参见IEEE 运算

  4. 下表列出了针对溢出禁用陷阱时的缺省结果。以下结果取决于舍入模式和中间结果的符号。

    舍入模式
    最近
    +∞
    -∞
    +∞
    -max
    向下
    +max
    -∞
    向上
    +∞
    -max

x86 浮点环境提供另一个未在 IEEE 标准中提到的异常:非正规操作数异常。当针对次正规数执行浮点运算时,会出现该异常。

异常的优先顺序如下所示:无效(优先级最高)、溢出、除、下溢、不精确(优先级最低)。 在基于 x86 的系统上,非正规操作数异常在所有异常中的优先级最低。

能够在单个运算中同时发生的标准异常只有不精确的溢出和不精确的下溢这两种组合。在基于 x86 的系统上,非正规操作数异常可以与五个标准异常中的任意一个同时发生。如果启用了对溢出、下溢和不精确的捕获,则溢出和下溢陷阱的优先级高于不精确陷阱;在基于 x86 的系统上,溢出、下溢和不精确陷阱的优先级都高于非正规操作数陷阱。