浮点数中整数的精确表示

时间:2018-08-29 22:23:24

标签: c++ floating-point precision

我试图理解浮点数格式的整数表示形式。

由于IEEE浮点格式的尾数只有23位,因此我希望任何大于1 << 22的整数都只是一个近似表示。这不是我在g ++中观察到的情况

下面的两个cout都打印相同的值33554432。

由于尾​​数部分是负责精度的部分,因此我们如何能够表示(存储)需要超过23位才能准确存储的精确数字。

void floating_point_precision(){
  cout<< setprecision(10);
  float fp = (1<<25);
  cout<< fp <<endl;
  cout<< (1<<25) <<endl;
}

作为基于以下答案的跟进,即使两个fp,i的打印内容不同,以下代码也为什么不执行“不等于”操作?

void floating_point_precision(){
  cout<< setprecision(10);
  float fp = ((1<<25)+1);
  cout<< fp <<endl;
  int i = ((1<<25)+1)  ;
  cout<< i <<endl;
  if(i != fp)
    cout<< "Not equal" <<endl;
}

1 个答案:

答案 0 :(得分:7)

确实,IEEE浮点只有有限数量的尾数位。如果有23个尾数位,那么它可以精确地表示2 23 个不同的整数值。

但是,由于浮点分别存储2的幂次幂,因此它可以(受限于有限的指数范围)表示2个 23 值中的任意一个次幂两个

33554432恰好是2 25 ,因此只需要一个尾数位即可准确表示它(加上一个二进制指数,表示乘以2的幂)。它的二进制表示形式是10000000000000000000000000,它有26位,但是只有1个 significant 位。 (嗯,实际上它们都很重要,但是您明白了。)

您会发现它的相邻整数值3355443133554433 不能完全用32位float表示。 (但是它们可以用64位double表示。)

更一般地,类型float的可连续表示的值之间的差异随值的大小而变化。在我的系统上(大多数系统使用IEEE格式,但是该标准对此没有要求),该程序:

#include <iostream>
#include <iomanip>
#include <cmath>

void show(float f) {
    std::cout << std::nextafterf(f, 0.0) << "\n"
              << f << "\n"
              << std::nextafterf(f, f*2) << "\n";
    putchar('\n');
}

int main(void) {
    std::cout << std::setprecision(24);

    show(1);
    show(1<<23);
    show(1<<24);
    show(1<<30);
}

产生以下输出:

0.999999940395355224609375
1
1.00000011920928955078125

8388607.5
8388608
8388609

16777215
16777216
16777218

1073741760
1073741824
1073741952

它显示类型为float的数字1、2 23 ,2 24 和2 30的直接前任和后继者。如您所见,数字越大,差距越大,每增加2的幂,差距就增加一倍。

使用doublelong double类型,您会得到相似的结果,但差距较小。