下溢如何导致上溢?

Rob*_*ton 5 c floating-point x86 underflow

我正在阅读英特尔手册(英特尔®64和IA-32体系结构软件开发人员手册* 2016),并且很好奇我是否正确理解了有关下溢异常需求的摘录:

提供了检测和处理下溢的功能,以防止很小的结果通过计算传播,并防止稍后产生另一个异常(例如,除法期间的溢出)。

-第4.9.1.5节

所以我的问题是这种情况是什么样的?一种可能的伪代码计算是

veryVerySmallNumber = SmallestFloatpossible -1
veryVeryLargeNumber = BigBigFloat
answer = veryVerySmallNumber / veryVeryLargeNumber
Run Code Online (Sandbox Code Playgroud)

我读到处理器可以通过两种方式处理此问题,但我更关心下溢可能导致溢出的方式。我还要感谢您对处理这些情况的一般精神作出任何澄清。

Eri*_*hil 10

英特尔对下溢的引用是关于浮点运算的。

该程序:

#include <stdio.h>

int main(void)
{
    float x = 0x1.23456p-70f;   //  Set x to a number around 2**-70.
    float y = x*x;
    float z = 1/y;
    printf("x = %g.\n", x);
    printf("y = %g.\n", y);
    printf("z = %g.\n", z);
}   
Run Code Online (Sandbox Code Playgroud)

在使用IEEE-754 binary32进行float打印的常见C实现中:

x = 9.63735e-22。
y = 9.29061e-43。
z = inf。

在中x*x,计算发生下溢-结果处于次正规范围内,在该范围内,float格式无法完全精确地表示它(尤其是在将结果四舍五入以适应格式时,结果的某些值会丢失)。

然后,由于数量太小,尝试取其倒数不会产生有限的结果-结果超出float了有限数的范围,因此产生了无穷大。据说该操作溢出。

英特尔硬件提供了一种检测下溢的方法:在未屏蔽FP异常的情况下,下溢异常实际上将被捕获(例如,在Linux / Unix上,操作系统将提供SIGFPE浮点异常)。或像平常一样屏蔽FP异常,它将在MXCSR中设置一个粘性标志位,以记录自上次异常状态标志清零以来发生了下溢异常。还有其他异常标志,用于溢出,不精确(非零舍入错误),无效(NaN结果)。请参阅MXCSR位的表,或参阅Intel x86手册。对于旧版x87,有类似的单独的屏蔽异常记录标志。

程序可以通过检测下溢x*x并执行其想要避免在以后的操作中完全失去对值的跟踪的任何步骤来利用此优势。

  • 这是一个很好的例子,说明IEEE Float具有逐渐下溢(子正常),但是对Inf而言是非渐进的*上溢*(因​​为exponent = max的所有有效模式都用在NaN有效载荷上,而不是更多的指数位或其他任何形式。) unum是一种有趣的替代实数格式,它也可以逐步溢出,而没有固定宽度的指数字段。(但完全没有inf / nan。)https://posithub.org/about和http://www.johngustafson.net/pdfs/BeatingFloatingPoint.pdf。IIUC,每个Posit都有一个可表示的逆,并且精度在+ -1.0左右对称,而float在0.0左右对称。 (2认同)