我正在阅读英特尔手册(英特尔®64和IA-32体系结构软件开发人员手册* 2016),并且很好奇我是否正确理解了有关下溢异常需求的摘录:
提供了检测和处理下溢的功能,以防止很小的结果通过计算传播,并防止稍后产生另一个异常(例如,除法期间的溢出)。
-第4.9.1.5节
所以我的问题是这种情况是什么样的?一种可能的伪代码计算是
veryVerySmallNumber = SmallestFloatpossible -1 veryVeryLargeNumber = BigBigFloat answer = veryVerySmallNumber / veryVeryLargeNumber
我读到处理器可以通过两种方式处理此问题,但我更关心下溢可能导致溢出的方式。我还要感谢您对处理这些情况的一般精神作出任何澄清。
英特尔对下溢的引用是关于浮点运算的。
该程序:
#includeint 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); }
在使用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
并执行其想要避免在以后的操作中完全失去对值的跟踪的任何步骤来利用此优势。