Why double can store bigger numbers than unsigned long long?

denis631 picture denis631 · May 5, 2015 · Viewed 11.1k times · Source

The question is, I don't quite get why double can store bigger numbers than unsigned long long. Since both of them are 8 bytes long, so 64 bits.

Where in unsigned long long, all 64 bits are used in order to store a value, on the other hand double has 1 for sign, 11 for exponent and 52 for mantissa. Even if 52 bits, which are used for mantissa, will be used in order to store decimal numbers without floating point, it still has 63 bits ...

BUT LLONG_MAX is significantly smaller than DBL_MAX ...

Why?

Answer

Damon picture Damon · May 5, 2015

The reason is that unsigned long long will store exact integers whereas double stores a mantissa (with limited 52-bit precision) and an exponent.

This allows double to store very large numbers (around 10308) but not exactly. You have about 15 (almost 16) valid decimal digits in a double, and the rest of the 308 possible decimals are zeroes (actually undefined, but you can assume "zero" for better understanding).
An unsigned long long only has 19 digits, but every single of them is exactly defined.

EDIT:
In reply to below comment "how does this exactly work", you have 1 bit for the sign, 11 bits for the exponent, and 52 bits for the mantissa. The mantissa has an implied "1" bit at the beginning, which is not stored, so effectively you have 53 mantissa bits. 253 is 9.007E15, so you have 15, almost 16 decimal digits to work with.
The exponent has a sign bit, and can range from -1022 to +1023, which is used to scale (binary shift left or right) the mantissa (21023 is around 10307, hence the limits on range), so very small and very large numbers are equally possible with this format.
But, of course, all numbers that you can represent only have as much precision as will fit into the matissa.

All in all, floating point numbers are not very intuitive, since "easy" decimal numbers are not necessarily representable as floating point numbers at all. This is due to the fact that the mantissa is binary. For example, it is possible (and easy) to represent any positive integer up to a few billion, or numbers like 0.5 or 0.25 or 0.0125, with perfect precision.
On the other hand, it is also possible to represent a number like 10250, but only approximately. In fact, you will find that 10250 and 10250+1 are the same number (wait, what???). That is because although you can easily have 250 digits, you do not have that many significant digits (read "significant" as "known" or "defined").
Also, representing something seemingly simple like 0.3 is also only possible approximately, even though 0.3 isn't even a "big" number. However, you can't represent 0.3 in binary, and no matter what binary exponent you attach to it, you will not find any binary number that results in exactly 0.3 (but you can get very close).

Some "special values" are reserved for "infinity" (both positive and negative) as well as "not a number", so you have very slightly less than the total theoretical range.

unsigned long long on the other hand, does not interprete the bit pattern in any way. All numbers that you can represent are simply the exact number that is represented by the bit pattern. Every digit of every number is exactly defined, no scaling happens.