我试图在一个循环中确定DBL_MIN(以测试另一个问题),我对输出感到惊讶:

double tmp(1.0);
double min(tmp);
while(tmp>0)
{
    tmp/=2.0;
    if(tmp>0) min=tmp;
        else break;
}

cout<<scientific<<endl;
cout<<"Computed minimum: "<<min<<endl;
cout<<"Defined minimum: "<<DBL_MIN<<endl;
if(min>0 && min<DBL_MIN) cout<<"min is between 0 and DBL_MIN, HUH!"<<endl;

exit(1);

输出为:
Computed minimum: 4.940656e-324
Defined minimum: 2.225074e-308
min is between 0 and DBL_MIN, HUH!

当最小的正值为2.2e-308时,min如何保持值4.94e-324?据我了解,DBL_MIN以下的正值不应代表。在Linux下的Core i7上使用GCC 4.9.2进行了测试。

最佳答案

DBL_MIN是最小归一化正值的两倍。这意味着这是其尾数不小于1.0的最小值。如果选择较小的尾数,仍然可以使用较小的数字。

因此,您得到的是Denormal number。正如维基百科所说,



IEEE 754 standard控制double(和其他浮点类型)的表示。该表示形式由指数e和尾数m(以及符号位,与该问题无关)组成。

对于指数e不等于零的情况,对应的double值为

(1 + m/2^52) * 2^(e-1023)

(^代表功率,52是m中的位数,因此m/2^52始终介于0到1(不包括0)之间。隐式(不包含在m中)1表示可以以这种方式存储的最小数字对应于m==0e==1(请记住,此表示形式为e!=0),其值为
2^(-1022)

大约是2.225074e-308,即DBL_MIN

但是,e==0以特殊方式处理。对于e==0,将删除隐式1,从而导致
(m / 2^52) * 2^(-1022)    // remember that e==0

这可以表示精确的零(使用m==0),也可以表示小的m的次正态(或非正态)。最小的数字是m==1,即2^(-1074)或大约。 4.940656e-324

10-02 06:49