我试图理解浮点数格式的整数表示形式。
由于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;
}
答案 0 :(得分:7)
确实,IEEE浮点只有有限数量的尾数位。如果有23个尾数位,那么它可以精确地表示2 23 个不同的整数值。
但是,由于浮点分别存储2的幂次幂,因此它可以(受限于有限的指数范围)表示2个 23 值中的任意一个次幂两个。
33554432
恰好是2 25 ,因此只需要一个尾数位即可准确表示它(加上一个二进制指数,表示乘以2的幂)。它的二进制表示形式是10000000000000000000000000
,它有26位,但是只有1个 significant 位。 (嗯,实际上它们都很重要,但是您明白了。)
您会发现它的相邻整数值33554431
和33554433
不能完全用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的幂,差距就增加一倍。
使用double
或long double
类型,您会得到相似的结果,但差距较小。