What differentiates the range for unsigned and signed types?
Why do we use the floating data types?
An IEEE754 64-bit double can represent any 32-bit integer, simply because it has 53-odd(a) bits available for precision and the 32-bit integer only needs, well, 32 :-)
It would be plausible for a (non IEEE754 double precision) 64-bit floating point number to have less than 32 bits of precision. That would allow truly huge numbers (due to the exponent) but at the cost of precision.
The bottom line is that, provided there are more bits of precision in the mantissa of the floating point number than there are in the integer (and enough bits in the exponent to scale it), then it can be represented without loss of precision.
(a) Technically, the 53rd bit of precision is an implied 1 at the start of the sequence so the amount of "variablity" may only be 52 bits. Whether it's 52 or 53, it's still enough bits to represent every 32-bit integer.
Yes. A float (or double) is guaranteed to exactly represent any integer that does not need to be truncated. For a double, there is 53 bits of precision, so that is more than enough to exactly represent any 32 bit integer, and a tiny (statistically speaking) proportion of 64 bit ones too.
The minimum ranges you can rely on are:
short intandint: -32,767 to 32,767unsigned short intandunsigned int: 0 to 65,535long int: -2,147,483,647 to 2,147,483,647unsigned long int: 0 to 4,294,967,295
This means that no, long int cannot be relied upon to store any 10-digit number. However, a larger type, long long int, was introduced to C in C99 and C++ in C++11 (this type is also often supported as an extension by compilers built for older standards that did not include it). The minimum range for this type, if your compiler supports it, is:
long long int: -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807unsigned long long int: 0 to 18,446,744,073,709,551,615
So that type will be big enough (again, if you have it available).
A note for those who believe I've made a mistake with these lower bounds: the C requirements for the ranges are written to allow for ones' complement or sign-magnitude integer representations, where the lowest representable value and the highest representable value differ only in sign. It is also allowed to have a two's complement representation where the value with sign bit 1 and all value bits 0 is a trap representation rather than a legal value. In other words, int is not required to be able to represent the value -32,768.
The size of the numerical types is not defined in the C++ standard, although the minimum sizes are. The way to tell what size they are on your platform is to use numeric limits
For example, the maximum value for a int can be found by:
std::numeric_limits<int>::max();
Computers don't work in base 10, which means that the maximum value will be in the form of 2n-1 because of how the numbers of represent in memory. Take for example eight bits (1 byte)
0100 1000
The right most bit (number) when set to 1 represents 20, the next bit 21, then 22 and so on until we get to the left most bit which if the number is unsigned represents 27.
So the number represents 26 + 23 = 64 + 8 = 72, because the 4th bit from the right and the 7th bit right the left are set.
If we set all values to 1:
11111111
The number is now (assuming unsigned)
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255 = 28 - 1
And as we can see, that is the largest possible value that can be represented with 8 bits.
On my machine and int and a long are the same, each able to hold between -231 to 231 - 1. In my experience the most common size on modern 32 bit desktop machine.