浮点溢出和不精确

时间:2020-03-10 21:20:06

标签: floating-point hardware fpu

我在处理英特尔硬件上的浮点错误时发现了一些不一致之处,我想知道这是英特尔硬件错误还是浮点算术工作原理的一般方式。场景:

1)10000 +最大流通量= 3.40282e + 38 产生错误:FE_INEXACT

2)maxfloat + maxfloat = inf 错误:FE_OVERFLOW,FE_INEXACT

3)1.1 * maxfloat = inf 错误:FE_OVERFLOW,FE_INEXACT

方案1与其他两个方案不一致,因为我超出了浮动范围,但没有像情况2和3那样溢出。

我无法理解为什么我没有溢出,并且在第一种情况下数字只是饱和,而在第二和第三个数字没有饱和的情况下,我会溢出。

#include <iostream>
#include <limits>
#include <cstdio>
#include <cfenv>

void print_error() {    
    const int err = fetestexcept(FE_ALL_EXCEPT);
    if (err & FE_INVALID) cout << "FE_INVALID " << endl;            
    if (err & FE_DIVBYZERO) cout << "FE_DIVBYZERO "<< endl;
    if (err & FE_OVERFLOW) cout << "FE_OVERFLOW "<< endl;        
    if (err & FE_UNDERFLOW) cout << "FE_UNDERFLOW " << endl;
    if (err & FE_INEXACT) cout << "FE_INEXACT " << endl;
    cout << endl;      
}

int main() {
    feclearexcept(FE_ALL_EXCEPT);        
    cout << numeric_limits<float>::max() + 100000.0f << endl;
    print_error();

    feclearexcept(FE_ALL_EXCEPT);        
    cout << numeric_limits<float>::max() + numeric_limits<float>::max() << endl;
    print_error();    

    feclearexcept(FE_ALL_EXCEPT);
    cout << 1.1f*numeric_limits<float>::max() << endl;
    print_error();
}

2 个答案:

答案 0 :(得分:3)

方案1与其他两个方案不一致,因为我超出了浮动范围,但没有像情况2和3那样溢出。

10000 + maxfloat不能精确表示,因此FE_INEXACT。相反,总和被四舍五入。舍入选择包括最大有限数maxfloat和第二个最大有限数“好像”,可以用其他指数范围表示。四舍五入到最接近值时,总和四舍五入到maxfloat,因为它更接近。

在情况2和3中,总和四舍五入到或大于此下一个最大的有限“好像”数字。由于四舍五入后的总和达到/超过此数字,因此将返回无穷大。


下面是一条数字线,显示了最后3个有限浮点,包括FLT_MAX
如果float的指数范围更大,则FLT_MAX之后的下2个数字将是右边的2:'FLT_MAX下一个“好像””且未命名。
“半程”在FLT_MAX和下一个最大的有限“好像”数字之间。

当总和大于FLT_MAX但小于“半路”时,四舍五入到最接近的结果为FLT_MAX(情况1)。当总和更大时,结果为无穷大。 (案例2,3)。

enter image description here

答案 1 :(得分:2)

在有限范围的上限处对有限结果进行舍入的方式是:

  • 计算如果指数范围永远持续,将产生什么可表示的数字。
  • 如果结果超出实际范围,则产生无限大并报告溢出和不精确。否则,请产生该数字(并在需要四舍五入时报告不准确的数字)。

这里的逻辑是,如果四舍五入总会产生一个在指数范围内的数字,那么就不会有溢出(即使数学结果超出了最大可表示的有限数,只要正常的四舍五入就可以将其取回)范围)。

IEEE-754 32位二进制文​​件中的最大有限值为2 128 -2 104 。如果指数范围不受限制,则下一个可表示的值为2 128

首先让我们看一下案例2和案例3。在情况2中,我们将最大值添加到自身,所以我们有(2 128 −2 104 )+(2 128 −2 104 )。从数学上来说,这是2 129 −2 105 。如果指数范围是无界的,这将是可表示的,因此不需要四舍五入;这将是结果。然后该数字的指数超出了实际的指数范围,因此将产生无穷大。

在情况3中,我们将最大有限值乘以1.1(由于1.1本身无法表示,因此它实际上必须是接近1.1的值)。因此,我们大约有(2 128 −2 104 )•1.1。实数结果将超过2 128 ,因此,如果指数范围不受限制,则浮点结果将超过2 128 。该数字的指数超出了实际的指数范围,因此将产生无穷大。

现在返回案例1。我们将10,000加到最大有限值,所以我们得到10,000 +(2 128 −2 104 )或2 128 −2 104 +10,000。最大有限值(2 128 −2 104 )和下一个可以无界指数范围表示的值(2 128 )是2 128 −2 105 。我们的实数结果2 128 −2 104 +10,000,小于该中点。因此,当使用最接近的四舍五入关系时,我们会将结果四舍五入为2 128 −2 104 。该数字在实际指数范围内(指数为127,我们只是将其表示为2 128 减去一点,而不是2 127 加很多)。结果就是这样。

因此10,000加上最大有限值将产生最大有限值。它仅“超过一点”超过了最大有限值,并被四舍五入。其他操作超出了最大有限值很多,并被四舍五入。

相关问题