浮点数中整数的精确表示形式

Exact representation of integers in floating points

本文关键字:表示 整数 浮点数      更新时间:2023-10-16

我正在尝试理解浮点格式的整数表示。

由于 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;
}

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

但是,由于浮点数单独存储 2 的幂指数,因此它可以(受有限的指数范围限制(准确地表示这2 23个值乘以 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) << "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

它显示了数字 1、2 23、224和 230的直接前身和后继者,类型为float。如您所见,对于较大的数字,差距会变大,在 2 的每个幂处,差距的大小会翻倍。

你会得到类似的结果,但差距较小,类型为doublelong double.