Floating point 浮点溢出和不精确性

Floating point 浮点溢出和不精确性,floating-point,hardware,fpu,Floating Point,Hardware,Fpu,我在英特尔硬件上处理浮点错误时发现了一些不一致的地方,我想知道这是英特尔硬件错误还是浮点算术的一般工作方式。场景: 1) 10000+maxfloat=3.40282e+38 产生错误:FE_不精确 2) maxfloat+maxfloat=inf 错误:FE_溢出,FE_不精确 3) 1.1*maxfloat=inf 错误:FE_溢出,FE_不精确 场景1与其他两个场景不一致,因为我超出了浮动范围,但并没有像案例2和3那样出现溢出 我不明白为什么我并没有得到溢出,在第一种情况下,数字只是饱和,

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

1) 10000+maxfloat=3.40282e+38 产生错误:FE_不精确

2) maxfloat+maxfloat=inf 错误:FE_溢出,FE_不精确

3) 1.1*maxfloat=inf 错误:FE_溢出,FE_不精确

场景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();
}
#包括
#包括
#包括
#包括
无效打印错误(){
常数int err=fetestexcept(FE_除所有外);
如果(错误和失效)不能
场景1与其他两个场景不一致,因为我超出了浮动范围,但没有像案例2和3那样出现溢出

总和
10000+maxfloat
不可精确表示,因此
FE_不精确
。取整总和。取整选项包括最大有限数
maxfloat
和下一个最大有限数“仿佛”它可以用额外的指数范围表示。如果四舍五入到最近,则四舍五入到
maxfloat
的和更接近

在案例2和案例3中,四舍五入到或高于下一个最大有限“仿佛”数的总和。由于四舍五入的总和满足/超过此数,因此返回无穷大


下面是显示最后3个有限浮点的数字行,包括
FLT\u MAX

如果float具有更大的指数范围,则
FLT_MAX
后面的2个数字将是右侧的2:“
FLT_MAX
next”as if“,”且未命名。
“中途”介于
FLT_MAX
和下一个最大的有限“仿佛”数之间

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

场景1与其他两个场景不一致,因为我超出了浮动范围,但没有像案例2和3那样出现溢出

总和
10000+maxfloat
不可精确表示,因此
FE_不精确
。取整总和。取整选项包括最大有限数
maxfloat
和下一个最大有限数“仿佛”它可以用额外的指数范围表示。如果四舍五入到最近,则四舍五入到
maxfloat
的和更接近

在案例2和案例3中,四舍五入到或高于下一个最大有限“仿佛”数的总和。由于四舍五入的总和满足/超过此数,因此返回无穷大


下面是显示最后3个有限浮点的数字行,包括
FLT\u MAX

如果float具有更大的指数范围,则
FLT_MAX
后面的2个数字将是右侧的2:“
FLT_MAX
next”as if“,”且未命名。
“中途”介于
FLT_MAX
和下一个最大的有限“仿佛”数之间

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


在有限范围的上端,舍入有限结果的方式是:

  • 计算如果指数范围永远持续,将产生的可表示数字
  • 如果结果超出实际范围,则生成无穷大并报告溢出和不精确。否则,生成该数字(如果需要任何舍入,则报告不精确)
这里的逻辑是,如果四舍五入无论如何都会产生指数范围内的数字,那么就不会有溢出(即使数学结果超过了可表示的最大有限数,只要正常的四舍五入会使其回到指数范围内)

IEEE-754 32位二进制文件中的最大有限值为2128−如果指数范围是无界的,下一个可重复的值将是2128

让我们先来看看案例2和案例3,在案例2中,我们将最大有限值加到它本身,所以我们得到了(2128)−2104) + (2128−数学上,这是2129−2105.如果指数范围是无界的,这是可表示的,因此不需要四舍五入;这就是结果。然后该数字的指数超出了实际指数范围,因此产生无穷大

在案例3中,我们将最大有限值乘以1.1(实际上必须是接近1.1的值,因为1.1本身是不可表示的)−2104)•1.1.实数结果将超过2128,因此,如果指数范围是无界的,浮点结果将超过2128。该数字的指数超出实际指数范围,因此产生无穷大

现在回到案例1,我们在最大有限值上加10000,得到10000+(2128)−2104)或2128−2104+10000。最大有限值(2128)之间的中点−2104),下一个可以用无界指数范围(2128)表示的值是2128−我们的实数结果是2128−2104+10000,小于该中点。因此,当使用“四舍五入到最近的平局到偶数”时,我们会将结果四舍五入到2128−这个数字在实际指数范围内(它的指数是127,我们刚才用2128减去一位,而不是2127加很多),所以它是结果


因此,10000加上最大有限值产生最大有限值。它只“稍微”超过最大有限值并向下舍入。其他操作大量超过最大有限值并向上舍入。

在u