寻找下一个浮点数

求比给定浮点数大的最小浮点数

这是清华大学软件学院雍俊海老师《软件工程(2)》课程的一道思考练习题。

实现实数类CP_Real的“++”和“–”运算符重载。要求“++”是将当前的浮点数变为下一个浮点数,即变为比当前浮点数大的最小浮点数。要求“–”是将当前的浮点数变为上一个浮点数,即变为比当前浮点数小的最大浮点数。

为此需要研究浮点数在计算机中实际的二进制表示……

我们知道只需要给尾数 +1 就可以了。

我们需要让编译器把浮点数当成整数,以让 CPU 进行整数的 +1 运算。问题是,我们必须防止编译器“自作聪明”地做强制转换。为此,我们先取地址,得到一个浮点数指针,然后强制转换为整型指针,此时内存中的数据并没有变化;送入 CPU 做完整数加法之后,再反过来做一遍……这样就骗过了编译器。

(我估计这件事用汇编语言来写……会更简单吧)

好在,从资料上学习了一种新的类型转换的运算符:( type & )。这就是我们要的,和强制转换并不一样,这个只是把内存中的数据重新解读,而没有做任何实质转换。

以下两种形式的作用相同。

*((int*)&a)
(int&)a

顺便指出,需要注意的是以下三种写法的意义互不相同。

(int)a
(int&)a
(int)&a

运算符重载的操作就不再赘述。下面贴测试代码。

//只对 IEEE 754,int 和 float 等长负责,可能有 bug
#include 
float increment(float a){
	int b=(((int&)a)+(a>=0?1:-1));
	return (float&)(b);
}

int main(){
	float samples[]={0, 0.1, 1e-9, 2.33, 1e20, -0.1, -1e-9, -2.33, -1e20};
	int n=sizeof(samples)/sizeof(float);
	for(int i=0; i

以上代码在 GCC 4.8.1 编译运行的结果是:

0.0000000000000000000000000000000000000000000000000000000000000000000000
0.0000000000000000000000000000000000000000000014012984643248171000000000

0.1000000014901161200000000000000000000000000000000000000000000000000000
0.1000000089406967200000000000000000000000000000000000000000000000000000

0.0000000009999999717180685400000000000000000000000000000000000000000000
0.0000000010000000827403710000000000000000000000000000000000000000000000

2.3299999237060547000000000000000000000000000000000000000000000000000000
2.3300001621246338000000000000000000000000000000000000000000000000000000

100000002004087730000.0000000000000000000000000000000000000000000000000000000000000000000000
100000010800180760000.0000000000000000000000000000000000000000000000000000000000000000000000

-0.1000000014901161200000000000000000000000000000000000000000000000000000
-0.0999999940395355220000000000000000000000000000000000000000000000000000

-0.0000000009999999717180685400000000000000000000000000000000000000000000
-0.0000000009999998606957660700000000000000000000000000000000000000000000

-2.3299999237060547000000000000000000000000000000000000000000000000000000
-2.3299996852874756000000000000000000000000000000000000000000000000000000

-100000002004087730000.0000000000000000000000000000000000000000000000000000000000000000000000
-99999993207994712000.0000000000000000000000000000000000000000000000000000000000000000000000

(完)

1 thought on “寻找下一个浮点数”

发表评论

电子邮件地址不会被公开。 必填项已用*标注