Geom
Geom

Reputation: 857

Determine DBL_MIN in a loop

I tried to determine DBL_MIN in a loop (in order to test another issue) and I was surprised by the output:

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);

The output is:

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

How can min hold the value 4.94e-324 when the smallest positive value is 2.2e-308 ? To my understanding positive values below DBL_MIN should not representable. Tested with GCC 4.9.2 on a Core i7 under Linux.

Upvotes: 3

Views: 250

Answers (1)

Petr
Petr

Reputation: 10007

DBL_MIN is minimum normalized positive value of double. This means that this is the minimum value that has its mantissa not less than 1.0. You can still go for smaller numbers if you choose smaller mantissa.

So what you get is Denormal number. As Wikipedia puts it,

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.

The IEEE 754 standard governs the representation of double (and other floating-point types). The representation consists of exponent e and mantissa m (and sign bit, which is irrelevant for this question).

For the exponent e not equal to zero, the corresponding double value is

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

(^ stands for power, and 52 is the number of bits in m, so that m/2^52 is always between 0 inclusive and 1 non-inclusive). The implicit (not included in m) 1 means that the minimal number that can be stored this way corresponds to m==0 and e==1 (remember that e!=0 for this representation), which gives the value of

2^(-1022)

which is approx. 2.225074e-308, that is DBL_MIN.

However, e==0 is treated in a special way. For e==0, the implicit 1 is dropped, resulting in

(m / 2^52) * 2^(-1022)    // remember that e==0

This allows for representation of exact zero (with m==0), and also for subnormals (or denormals) for small m. The smallest possible such number is for m==1, that is 2^(-1074), or approx. 4.940656e-324.

Upvotes: 2

Related Questions