![]() |
|||
![]() ![]() |
![]() |
![]()
|
![]() |
Floating-Point NumbersIntegers arent the only kind of number you need. Java also provides support for rational numbers numbers with a decimal point like 106.53 or -78.0987. For reasons youll learn shortly, these are called floating-point numbers, and Java has two primitive data types for them: the float and the double. Floating-point literals can be made quite large or quite small by writing them in exponential notation for example, 1.0E89 or -0.7E-32. The first is 1.0 × 1089, in other words 1 followed by 89 zeroes. The second is -0.7 × 10-32 or -0.00000000000000000000000000000007. A floating-point number can be split into three parts: the sign, the mantissa, and the exponent. The sign tells you whether the number is positive or negative. The mantissa tells you how precise the number is. Generally, the more digits a number has, the more precise it is. Finally the exponent tells you how large or small the number is. In the number 0.7E-32, the sign is -, the mantissa is 7, and the exponent is -32. In 1.0E89, the sign is +, the mantissa is 1, and the exponent is 89. Although Java does not put any particular limits on the number of digits a float or double literal can have before the decimal point, it is customary to place exactly one non-zero digit before the decimal point and all the rest after it and adjust the exponent to compensate. Thus, instead of writing 15.4 × 1089, you would write 1.54 × 1090. This is called scientific notation. An alternative custom called exponential notation places the first non-zero digit immediately following the decimal point. In exponential notation, 15.4 × 1089 becomes 0.154 × 1091. The advantage to such a custom is that you no longer actually have to write the decimal point. If you know that the decimal point is always going to be immediately after the first non-zero digit, as it is in scientific notation, then why bother writing it down? Of course, not writing it makes it harder for human beings to read and understand the number, so the decimal point is required in Java source code. Computers can do quite well without an explicit decimal point as long as the byte code sticks to a form of scientific notation. Once weve agreed that floating-point numbers will always be written in scientific notation, the mantissa, exponent, and sign of a floating-point number can all be written as integers. Just like the sign bit in integer data types, 1 represents a positive number and 0 represents a negative number. For example, 15.4 has sign 1, mantissa 154, and exponent 1. The number -0.7 × 10-32 has sign 0, mantissa 7, and exponent -32. Representing floating-point numbers in binary codeTo represent a floating-point number in a computer, you must convert each of these values into bits and binary notation. Converting a number with a decimal point into binary notation is only slightly harder than converting a number without a decimal point. When you write the number 10.5, you mean one ten, no ones, and five tenths. In binary notation you use a binary point rather than a decimal point (though they look exactly the same on the printed page.) Thus, a real number in binary notation looks like 1010.1. This means a number with one eight, no fours, one two, no ones, and one half. In other words, this is 8 + 2 + 0.5 = 10.5 in decimal notation. Binary floating-point numbers in Java are written in normalized form. This means that the leftmost one is shifted to the immediate right of the binary point. An exponent is then added as a power of two. Thus 1010.1 becomes 0.10101 × 10100 (where 10100 is 24 in decimal). The sign is 1, the mantissa is 10101, and the exponent is 100. But wait! It gets better. When youre using binary notation, the only non-zero digit is 1. The first non-zero digit after the binary point must be 1 because it cant be anything else. Therefore, you dont need to write it down either. You get an extra bit of precision, essentially for free. To store the mantissa 10101, you only need to write the bits 0101. The next step is to determine how these numbers will be stuffed into bytes. Java allots four bytes for each float and eight bytes for each double. The first bit of each float is used for the sign bit. A 1 bit is negative and a 0 bit is positive, exactly as with integers. The next eight bits are used for the exponent. These eight bits are treated as an unsigned integer between 0 and 255. The numbers 0 and 255 have special meanings that I discuss shortly. Otherwise, the exponent is biased by subtracting 127 from it. Therefore, float exponents have values between -126 (1 - 127) and +127 (254 - 127). Heres what this arrangement looks like: 01111111111111111111111111111111 00000000000000000000000000000001 1000000000000000000000000000000 The final 23 bits are used for the mantissa. The mantissa is given as a fractional number between 1 and 2. As discussed earlier in this chapter, the first bit is assumed to be one, so the mantissa effectively has 24 bits of precision. Extra zeroes are appended if necessary. This doesnt change the number, though, because 1.0101000000000000000000 is exactly the same as 1.0101. In other words, you can always add extra zeroes at the end of the mantissa to fill space. Figure 2-1 shows the bits in a float.
|
![]() |
|