Reputation: 446
I'm taking an introductory course in programming (in java) and I'm interested in understanding why the ranges of the primitive data types in java are as they are. When it comes to integer-like data types like a byte, it seems easy to understand why it only accepts values from -128 to 127; a byte has a size of 8 bits, which can take up to 256 values, so we can assign to each of these 256 values a natural number, which I believe is what is happening behind the curtain. It also explains why 128 is excluded: we have 128 negative numbers, 127 positives, and zero. These add up to 256 already. There is no bijection between [1,256] and [-128,128].
This idea makes sense in regards to the ranges of all the integer-like data types, but when it comes to floating-points, one sees some strange ranges. For example the range of a double is [-2^{1074},(2-2^{-52})2^{1023}]. Why is this the case?
I apologize for the cumbersome notation, apparently I can't use latex here.
Upvotes: 1
Views: 720
Reputation: 222659
Java uses the IEEE-754 binary64 format. In this format, one bit represents a sign (+ or − according to whether the bit is 0 or 1), eight bits are used for an exponent, and 52 bits are used for the primary encoding of the significant. One bit of the 53-bit significand is encoded via the exponent.
The values of the exponent field range from 0 to 2047. 2047 is reserved for use with infinities and NaNs. 0 is used for subnormal numbers. The values 1 to 2046 are used for normal numbers. In this range, an exponent field value of E represents an exponent e = E−1023. So the lowest value of e is 1−1023 = −1022, and the highest value is 2046−1023 = 1023. An exponent field value of 0 also represents the lowest value of E, −1022.
The 53-bit significand represents a binary numeral d.ddd…ddd2, where the first d is 0 if the exponent field is 0 and 1 if the exponent field is 1 to 2046. There are 52 bits after the “.”, and they are given by the primary significand field.
Let S be the sign bit field, E be the value of the exponent field, and F be the value of the primary significand field as an integer. Then the value represented is:
Now we can see the smallest positive number is represented when S is 1, E is 0, and F is 1 (00000000000000000000000000000000000000000000000000012). Then the value represented is (−1)0 • 2−1022 • (0 + 1•2−52) = +1 • 2−1022 • 2−52 = 2−1074.
The greatest finite number is represented when S is 1, E is 2046, and F is 252−1 (11111111111111111111111111111111111111111111111111112). Then the value represented is (−1)0 • 22046−1023 • (1 + (252−1)•2−52 = +1 • 21023 • (1 + 1 − 2−52) = 21023 • (21 − 2−52) = 21024 − 2971.
Upvotes: 1
Reputation: 381
It's the same thing for floating-point values as for integer values - the number of bits available.
An IEEE double-length floating point value has 64 bits, used as follows:
Sign bit: 1 bit
Exponent: 11 bits
Significand precision: 52 bits
The significand is a binary fraction, the maximum value (all bits set) is therefore somewhat less than one.
The exponent has value 0 to 2047, or -1024 to +1023. That gives you the approximate range of 2 to the -1024 to 2 to the +1023 (it's actually less since a couple of values are reserved for specific use).
Wikiipedia for more exact details
Upvotes: 0