我必须实现一个程序来计算机器epsilon
浮动
和
双重的
.
我编写了这些函数:
int feps(){
//machine epsilon for float
float tmp=1;
int d=0;
while(1+(tmp=tmp/2)>1.0f)d++;
return d;
}
int deps(){
//machine epsilon for double
double tmp=1;
int d=0;
while(1+(tmp=tmp/2)>1.0)d++;
return d;
}
笔记
:
64位机器编译器gcc 4.9.1目标:x86_64-linux-gnu
32位机器编译器gcc 4.8.2目标:i686 linux gnu
我在一个
64
钻头机,结果是:
浮动23
双52
正如我所料,然后我在
32
比特虚拟机,结果非常奇怪:
浮动63
双63
我还尝试用
-mpc32型
,
-mpc64型
和
-英里80
结果如下:
-mpc32型
浮点23,双23
-mpc64型
浮动52,双52
-英里80
浮点63,双63
我也在64位机器中尝试了这些编译选项,但结果总是23和52。
我知道float是单精度的,double是双精度的,但我的32位虚拟机的编译器可能使用了
binary80
浮点数和双精度的格式?
我很确定我的代码是正确的,所以我认为问题与编译器有关,或者是更微妙的问题。
我花了一整天的时间搜索浮点的相关信息,也读了一些MMX/SSE指令的相关内容,但我不太理解,还有一些关于x87 FPU的内容可能会产生一些问题。
更新:
我要感谢所有帮助我的人,我设法获得了32位虚拟机中float和double的真正epsilon值,这是代码:
int feps(){
float tmp=1;
int d=0;
float tmp2=1;
do{
tmp2=1+(tmp=tmp/2);
d++;
}while(tmp2>1.0f);
return d-1;
}
int deps(){
double tmp=1;
int d=0;
double tmp2=1;
do{
tmp2=1+(tmp=tmp/2);
d++;
}while(tmp2>1.0);
return d-1;
}
正如您所看到的,我们需要将中间结果放入一个变量中,这样我们可以防止1+(tmp=tmp/2)被计算为
长双
在循环测试中。