Java (week 3) BSc Design for Digital Media Introduction to Java Programming Week 3 The Numeric Data Types Contents Data Types - Numbers Integer Types The int data type The long data type The shortand byte data types Real (Floating Point) Types The float data type The double data type Mixing Data Types Implicit Type Conversion Casts Data Types - Numbers Last week we discussed the notion of data types in Java. This means, that variables in Java have to be declared to have some sort of data type. It enforces certain rules about only being able to assign the appropriate type of data to variables. Strictly typed languages (like Java) give the compiler the ability of being able to tell the type of any expression, i.e. the data type of the result obtained when evaluating an expression. This can be done at compile time and ensures that we do not get type incompatability errors when we are running the program. Strict typing means that we have to very aware of the type of any expressions we put into our programs. Expressions can crop up in many places in Java programs, e.g. on the right hand side of an assignment statement or as an actual parameter in a method invocation. This strict typing makes our programs less error prone at the expense of some flexibility in the way our programs work. Java provides several different data types to accommodate most of our data needs. We will look initially at the data types Java provides for dealing with numbers. We will look later at storing non-numeric data. Integer Types As we have mentioned previously, integer variables are used to store numbers with no fractional part. Numbers such as -23, 0, 1, 25647, -1, 32451, etc. In a Java program, integer literals are shown as numbers with no decimal points. As soon as you put a decimal point into a literal it is no longer an integer. Integers are represented exactly in the computer's memory. Arithmetic Operators Arithmetic operators are one of the ways in which we can construct expressions in Java programs. The following is a summary of the main arithmetic operators which can be applied to integer values. In the table we assume that the values we are dealing with are integers, i.e. the numbers we are adding, subtracting , etc. are all integers. If these operators are applied to integers we will get an integer result. Operator Meaning * multiplies the first value by the second value giving their product (which is also an integer). / divides the first value by the second value giving the number of times the second value goes into the first value (this is also an integer). % gives the remainder on dividing the first value by the second value. + adds two integer values together producing their sum (which is also an integer) - subtracts the second value from the first value producing their difference (which is also an integer). N.B. this symbol can also be placed before a single value or an expression in order to negate the value. The int Data Type We have already seen how to declare variables to be of type int. We use the keyword int. int height; This declares a variable called height and says that it is of type int. Consider the following example, which contains a number of expressions built by using int variables and the arithmetic operators. /* * IntDemo.java * * Created on 14 October 2002, 11:53 */ import java.awt.*; /** * * @author dave */ public class IntDemo extends java.applet.Applet { public void paint(Graphics g){ int number1 = 12 ; int number2 = 7 ; int number3 = 4 ; int result ; g.drawString("number1 is "+number1+" number2 is "+number2 +" number3 is "+number3, 10,20); result = number1 + number2 ; g.drawString("The sum of number1 and number2 is "+result, 10,50); result = number1 - number2 ; g.drawString("The difference of number1 and number2 is "+result, 10, 70); result = number1 * number2 ; g.drawString("The product of number1 and number2 is "+result, 10, 90); result = number1 / number2 ;
g.drawString("The quotient of number1 and number2 is "+result, 10, 110);
result = number1 % number2 ;
g.drawString("The remainder on dividing number1 by number2 is "+result, 10, 130); result = number1 * number2 + number3 ;
g.drawString("number1 * number2 + number3 is "+result, 10, 150);
/* Note that * operations are done before + operations */
result = number1 + number2 * number3 ;
g.drawString("number1 + number2 * number3 is "+result, 10, 170);
result = number1 * number2 + number3 * number2 ;
g.drawString("number1 * number2 + number3 * number2 is "+result, 10, 190);
/* Notice that brackets can be used to change the evaluation order in an
* arithmetic expression - anything in brackets is evaluated first
*/
result = number1 * (number2 + number3) ;
g.drawString("number1 * (number2 + number3) is "+result, 10, 210);
/* The minus operator - has got the same precedence as addition +
* The divide operator / has got the same precedence as multiplication *
*/
result = number1 - number2 / number3 ;
g.drawString("number1 - number2 / number3 is "+result, 10, 230);
/* Where operators of equal precedence occur we calculate the leftmost
* operation first
*/
result = number2 * number1 - number2 / number3 + number2 - number1;
g.drawString("number2 * number1 - number2 / number3 + number2 - number1 is "+
result, 10, 250);
}
}
This shows a number of interesting aspects of integer expressions and the arithmetic operators. Precedence The arithmetic operators have a precedence (or order of importance) when it comes to evaluating arithmetic expressions. The operators *, /, % have a higher precedence (but all three are of equal precedence to each other) than the operators + and - (both of which have the same precedence as each other). Hence the colour coding in the above table of operators. This means that when we evaluate Arithmetic expressions the high precedence operators are evaluated first, before any of the low precedence operators. Where we have operators of equal precedence in an expression, we evaluate the leftmost operator first. We can change the order of evaluation in an expression by using round brackets. Sub-expressions inside brackets will be evaluated first. It is useful to know the precedence of operators, but when in doubt use brackets. Size Restrictions We cannot store very large values using the int data type. All implementations of Java use 32 bits in memory to represent ints. This means we can only store numbers between the value of -2147483648 and 2147483647. It is instructive to see what happens when we violate this restriction. Consider the following applet: /* * LargeInts.java * * Created on 15 October 2002, 12:25 */ import java.awt.*; /** * * @author dave */ public class LargeInts extends java.applet.Applet { public void paint(Graphics g){ int large = 2147483647 ; g.drawString("A large integer is "+large, 10, 20); int veryLarge = large + 1 ; g.drawString("A very large integer is "+veryLarge, 10, 40); } }
The result is very unexpected. Adding one on to the largest int we can represent gives us a large but negative value. Something equally unexpected happens when we subtract from the largest negative value. You might have thought that the Java interpreter would have generated an error of some sort, but that is not the case. This means that we need to be very aware of the size of numbers we are dealing with when it comes to integers. The long data type Fortunately, we have a data type that can represent larger integers. In all implementations of Java long integers are represented using 64 bits and can represent values between -9223372036854775808 and 9223372036854775807. This should be adequate for even very demanding numerical tasks. However, we still have to be careful when using long integers, since the same thing can happen if we need to represent numbers outwith the stated range of the long data type. To declare a long integer variable we use the long keyword, e.g. long veryBigNumber; This declares veryBigNumber to be a variable of type long. /* * LongInts.java * * Created on 15 October 2002, 12:25 */ import java.awt.*; /** * * @author dave */ public class LongInts extends java.applet.Applet { public void paint(Graphics g){ long large = 2147483647 ; g.drawString("A large integer is "+large, 10, 20); long veryLarge = large + 1 ; g.drawString("A very large integer is "+veryLarge, 10, 40); }
}
The short and byte data types These allow us to use smaller amounts of storage space to store our integer values. We use the keywords short and byte to declare variables of these types. We might use these if we wanted to cut down the amount of memory needed to run our program Short integers use 16 bits to represent numbers. The range of values is -32768 to 32767. Byte integers use 8 bits (a byte) to represent numbers. The range of values is -128 to 127. Real (Floating Point) Types Sometimes we wish to represent numbers within our programs which have fractional parts. For instance, if we are storing someone's height in metres it is likely that we will want to store height other than 1 or 2. This wouldn't be very accurate. We could instead say that someone's height is 1.73 metres. We can represent such numbers using real (a.k.a. floating point) data types. As we shall see these types are called float and double. The operators we used on the integers work with real data as well, except that the division operator behaves slightly differently. Our result can contain a fractional part. If we divide the real value 31.0 by the value 2.0 we get the result 15.5 N.B. We should be aware that floating point numbers are sometimes only approximately represented within the computer. Floating point values, depending on the number of bits they use to represent a number, have the capability of giving a value to a certain number of significant figures. This is known as the precision of the data type. This is a slight problem with real data types. We can only represent some real numbers approximately inside the computer. If we divide 2 by 3 we get the value two thirds which can only be approximated as 2.333333 where we assume we have an infinite number of 3s after the point. Also as a consequence of the number of bits used to represent the number each type has a range of values it can represent. These ranges are normally very large. The float data type This data type is a real number data type. Java uses 32 bits to store a float value. The range of values go from +3.4e+38 to +1.4e-45 with a precision of between 6 and 7 significant figures. The notation with the e in it is known as scientific notation. The e means times 10 to the power of whatever follows. 1.4e-45 means 1.4 times10 to the power -45 (a very small number), that is 0.00000000000000000000000000000000000000014 (that's with 44 zeros between the decimal point and the 1). When we want to declare a variable of type float we use the float keyword in the declaration, e.g. float heightInMetres; This declares a variable heightInMetres which can store float values. When we wish to write float literals we use the letter f (or F) after the literal to specify that it is a float value rather than any other type. For example, 3f
2.5f
0.123F
-2.0005f are all float literals. We can use scientific notation for our float literals using e (or E), e.g. 3e-34f
-2.3E+33f
0.f
0.12e8f are all float literals. /* * FloatDemo.java * * Created on 15 October 2002, 13:43 */ import java.awt.*; /** * * @author dave */ public class FloatDemo extends java.applet.Applet { /** Initialization method that will be called after the applet is loaded * into the browser. */ public void init() { } public void paint(Graphics g){ float number1 = 2.5f ; // putting an f after a constant makes it of type float float number2 = 3.0f ; float result; result = number1 * number2 ; g.drawString("number1 * number2 is "+result, 10,20); result = number1 / number2 ; g.drawString("number1 / number2 is "+result, 10,40); } }
The double data type The double data type is like the float data type except that it uses 64 bits to represent each number. Therfor it has a larger range +1.79e+308 to +4.9e-324 with an increased precision of 14 to 15 significant figures. We use the keyword double to declare a double variable. double moleculeDiameter; This declares a variable called moleculeDiameter to be of type double. To write double literals we use d (or D) instead of f (or F) for floats. N.B. If we omit the f or the d then Java will assume that our literal is a double. This means that the following are all double literals. 3d
2.5d
0.123D
-2.0005d
3e-34d
-2.3E+33d
0.d
0.12e8
0.1
34e10
1.9e-100
/* * DoubleDemo.java * * Created on 15 October 2002, 12:52 */ import java.awt.*; /** * * @author dave */ public class DoubleDemo extends java.applet.Applet { /** Initialization method that will be called after the applet is loaded * into the browser. */ public void init() { } public void paint(Graphics g){ double number1 = 2.5 ; // with no f Java assumes this is a double double number2 = 3.0 ; double result; result = number1 * number2 ; g.drawString("number1 * number2 is "+result, 10,20); result = number1 / number2 ; g.drawString("number1 / number2 is "+result, 10,40); } }
Mixing Types We can write expressions which mix data types. But wait a minute, doesn't that violate the strict typing rules of Java. It would if we couldn't predict what the final type of any expression would be. However we can still predict this by the use of a consistent rule for mixing data types. This type of mixing will result in the conversion of data values of some types into other data types. This conversion can take place in two ways. Implicit Type Conversion This is where we don't specify which conversions to make. The Java compiler decides automatically. If we take the data types we have just looked at, we can arrange them into a strict hierarchy. double highest type float long int short byte lowest type If an expression contains more than one type then we convert the type of all values in the expression to the highest type which appears in the expression. so mixing doubles and floats will result in all values being implicitly converted to doubles. This also means that we can assign values of a type lower in the hierarchy to a variable of a type higher in the hierarchy, with no loss of accuracy. So we can assign an int to a float, but not the other way around, e.g. we can do float height = 3 ; but we cannot do int i = 3.45f;
Casts (Explicit Conversion) If we wish to convert the type of a higher data type to a lower data type we can use a cast. This indicates that there could be a possible loss of data when doing the conversion. The cast is shown in round brackets which contain the name of the type to which we are converting and is placed immediately before the item we are converting, e.g. int i = (int) 3.45f; This converts the float value 3.45f to an int. Notice that this results in the value 3, since ints cannot hold a fractional part. /* * MixedDemo.java * * Created on 15 October 2002, 12:55 */ import java.awt.*; /** * * @author dave */ public class MixedDemo extends java.applet.Applet { public void paint(Graphics g){ int number1 = 20 ; float number2 = 10.5f ; double number3 = 5.0 ; long number4 = 6 ; int resultInt ; float resultFloat; double resultDouble; resultInt = (int) number4 ; g.drawString("Result is "+resultInt, 10,20); } } Top Of Page Back to Main Page David Crossen, February 2003 ��
�