浮点中整数的精确表示

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浮点中整数的精确表示相关的知识,希望对你有一定的参考价值。

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

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

下面的两个法院都打印相同的值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;
}
答案

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

但由于浮点单独存储一个2的幂指数,它可以(受限于指数范围)代表那些223值乘以2的幂的任何一个。

33554432正好是225,所以它只需要一个尾数位来表示它(加上一个表示乘以2的幂的二进制指数)。它的二进制表示是10000000000000000000000000,它有26位但只有1位有效位。 (嗯,实际上它们都很重要,但你明白了。)

您会发现它的相邻整数值3355443133554433无法在32位float中精确表示。 (但它们可以用64位double表示。)

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

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

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

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,223,224和230.正如您所看到的,对于较大的数字,间隙变大,每个幂为2时间隙的大小加倍。

您会得到类似的结果,但间隙较小,类型为doublelong double

以上是关于浮点中整数的精确表示的主要内容,如果未能解决你的问题,请参考以下文章

如何将浮点值转换为具有精确精度的整数,例如 123.3443 到 1233443?

精度浮点型数据精确到了几位小数呢?

深入理解计算机系统(2.7)------二进制小数和IEEE浮点标准

深入理解计算机系统(2.7)------二进制小数和IEEE浮点标准

允许这种浮点优化吗?

c语言如何让输出结果精确到两位小数