Floating Point Variables
You may have noticed something a little funny about the above output. The numbers aren’t exactly correct. Zero degrees Fahrenheit is actually -17.778 degrees Celsius, not -18 degrees Celsius as this program reports. The problem is that we used only integers here, not decimal numbers. In computer-speak decimal numbers are called “floating point numbers.”
Floating point numbers can represent a broader range of values than integers. For example you can write very large numbers like the speed of light (2.998E8 meters per second) and very small numbers like Plank’s constant (6.63E-27 ) using the same number of digits. On the other hand you lose some precision that you probably didn’t need for such large and small numbers anyway.
Some languages have a third kind of number called a fixed point number. This number has a set precision, for instance two decimal places, and is often useful in monetary calculations. Java has no fixed point data type.
Using floating point numbers is no harder than using integers. We can make our Fahrenheit to Celsius program more accurate merely by changing all our int
variables into double
variables.
// Print a more accurate Fahrenheit to Celsius table
class FahrToCelsius {
public static void main (String args[]) {
double fahr, celsius;
double lower, upper, step;
lower = 0.0; // lower limit of temperature table
upper = 300.0; // upper limit of temperature table
step = 20.0; // step size
fahr = lower;
while (fahr <= upper) { // while loop begins here
celsius = 5.0 * (fahr-32.0) / 9.0;
System.out.print(fahr);
System.out.print(" ");
System.out.println(celsius);
fahr = fahr + step;
} // while loop ends here
} // main ends here
} //FahrToCelsius ends here
I’ve made one further change to the Fahrenheit to Celsius program. All the integer constants in the program like 5
and 9
have become 5.0
and 9.0
and so on. If a constant number includes a decimal point, then the compiler assumes it’s a double precision floating point number. If it doesn’t then the compiler assumes it’s an integer. However when two numbers of different types such as integer and floating point are involved in a calculation on the right hand side of an equation, the compiler promotes the number of the weaker type to the stronger type before doing the calculation.
What makes one type of number stronger than another? It’s the ability to represent a broader spectrum of numbers. Since a byte can only represent 256 numbers it’s weaker than a short which can stand for 65,535 different numbers including all the numbers a byte can represent. Similarly an int
is stronger than a short
. Floating point numbers are stronger than any integer type and doubles are the strongest type of all.
Therefore we could have left all the small constants as integers and the program output would have been unchanged. However it is customary to put in decimal points to remind yourself and anyone else who may be unlucky enough to have to read your code, exactly what is going on.
This applies to calculations that take place on the right hand side of an equal sign. The left hand side of the equals sign is a different story. In fact it’s so different that programmers have given the different sides of the equals sign special names. The left-hand side is called an lvalue while the right hand side is called an rvalue.
An rvalue is a calculated result and as specified above it takes on the strongest type of any number involved in the calculation. On the other hand the lvalue has a type that must be defined before it is used. That’s what all those float fahr, celsius;
statements are doing. Once the type of an lvalue is defined it never changes. Thus if we declare fahr
to be an int
, then on the left hand side of an equals sign fahr
will always be an int
, never a float
or a double
or a long
.
If you’ve been following along you may notice a problem here. What if the type on the left doesn’t match the type on the right? e.g. what happens with code like the following?
class FloatToInt {
public static void main (String args[]) {
int myInteger;
myInteger = 9.7;
} // main ends here
} //FloatToInt ends here
Two things can happen. If, as above, we’re trying to move a number into a weaker type of variable, the compiler generates an error. On the other hand if we’re trying to move a weaker type into a stronger type then the compiler converts it to the stronger type. For instance the following code is legal:
class IntToFloat {
public static void main (String args[]) {
float myFloat;
int myInteger;
myInteger = 9;
myFloat = myInteger;
System.out.println(myFloat);
} // main ends here
} //IntToFloat ends here
Exercises
- Have the FahrToCelsius program print a heading above the table.
- Write a similar program to convert Celsius to Fahrenheit.