4.4.3. 异常

浮点算术运算可能会遇到各种问题。 例如,计算结果可能太大或太小而不符合格式要求,或者无法计算出结果(如试图求负数的平方根或用零除以零)。 这些称为异常,因为它们表示例外或异常情况。

ARM 浮点环境可使用多种方法处理异常。

忽略异常

系统生成并返回似是而非的运算结果。 例如,负数的平方根可能会生成 NaN,而试图计算太大而不符合格式要求的值可能会生成无穷大。 如果发生异常并将其忽略,则会在浮点状态字中设置一个标记,指示在过去某一时刻出现错误。

捕获异常

这意味着,在发生异常时,将运行一个称为捕获处理程序的代码块。 系统提供了一个缺省捕获处理程序,它输出一条错误消息并终止应用程序。 但是,您可以提供自己的捕获处理程序,按照所选择的方式消除异常情况。 捕获处理程序甚至可以提供从运算返回的结果。

例如,如果算法可方便地假定 0 除以 0 得 1,则可以为“无效运算”异常提供一个自定义捕获处理程序,以识别这种特殊情况并替换所需的结果。

异常类型

ARM 浮点环境可识别以下类型的异常:

  • 如果运算没有合理的结果,则会发生“无效运算”异常。 发生这种异常的原因可能是:

    • 对信号 NaN 执行任何运算,最简单的运算(复制和更改符号)除外

    • 将正无穷大和负无穷大相加,或将无穷大与其自身相减

    • 将无穷大乘以零

    • 将零除以零,或将无穷大除以无穷大

    • 求任意数除以零或无穷大除以任意数的余数

    • 求负数的平方根(不包括负零)

    • 在结果不符合格式要求时,将浮点数转换为整数

    • 在两个数中的一个是 NaN 时进行比较。

    如果未捕获“无效运算”异常,所有这些运算将返回无提示 NaN;到整数的转换除外,它返回的是零(因为整数中没有无提示 NaN)。

  • 如果将非零的有限数除以零,则会发生“除以零”异常。 (将零除以零发生“无效运算”异常。 将无穷大除以零有效并返回无穷大。)

    如果未捕获“除以零”,该运算将返回无穷大。

  • 如果运算结果太大而不符合格式要求,则会发生“溢出”异常。 例如,如果将最大可表示数(Table 4.14 中标记为 d)与自身相加,则会发生这种异常。

    如果未捕获“溢出”,运算将返回无穷大或最大有限数,具体取决于舍入模式。

  • 如果运算结果太小而无法表示为规格化数(Exp 至少为 1),则会发生“下溢”异常。

    导致发生“下溢”的情况取决于是否将其捕获:

    • 如果捕获“下溢”,只要结果太小而不能表示为规格化数,就会发生“下溢”异常。

    • 如果未捕获“下溢”,仅当需要舍入结果时才会发生“下溢”异常。 因此,举例来说,将 float0x00800000 除以 2 时不会生成“下溢”信号,因为结果 (0x00400000) 是精确的。 但是,如果尝试将 float 数 0x00000001 乘以 1.5,则会生成“下溢”信号。

      (对于熟悉 IEEE 754 规范的读者,ARM 编译器中选择的实现选项可用于在舍入之前检测极小值,并检测不精确结果的精度下降情况。)

      如果未捕获“下溢”,则根据当前舍入模式,将结果舍入到两个最接近的可表示非正规数中的一个。 将忽略精度下降,系统返回可能的最佳结果。

    • 只要运算结果需要舍入,就会发生“不精确结果”异常。 如果需要在软件的每个运算中都检测此异常,则会使速度显著下降,因此,普通浮点库不支持“不精确结果”异常。 增强型浮点库和硬件浮点系统均支持“不精确结果”。

      如果未捕获“不精确结果”,系统将按通常方式舍入结果。

      如果未捕获“溢出”和“下溢”中的任何一个,它们也会设置“不精确结果”标记。

缺省情况下,不捕获所有异常。

Copyright © 2007 ARM Limited. All rights reserved. ARM DUI 0349AC
Non-Confidential