循环判断DBL_MIN

Determine DBL_MIN in a loop

我试图在循环中确定 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 是 double 的最小 标准化 正值。这意味着这是尾数不小于 1.0 的最小值。如果您选择较小的尾数,您仍然可以选择较小的数字。

所以你得到的是Denormal number。正如维基百科所说,

In a normal floating-point value, there are no leading zeros in the significand; instead leading zeros are moved to the exponent. So 0.0123 would be written as 1.23 × 10−2. Denormal numbers are numbers where this representation would result in an exponent that is below the minimum exponent (the exponent usually having a limited range). Such numbers are represented using leading zeros in the significand.

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

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

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

^代表幂,52是m中的位数,所以m/2^52总是在0含和1不含之间)。隐含的(不包括在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.