CHAPTER 4: Types, Values, and Variables Previous
Previous
Java Language
Java Language
Index
Index
Next
Next

4.2 Primitive Types and Values

4.2.1 Integral Types and Values , 4.2.2 Integer Operations , 4.2.3 Floating-Point Types and Values , 4.2.4 Floating-Point Operations , 4.2.5 The boolean Type and boolean Values

A primitive type is predefined by the Java language and named by its reserved keyword (S3.9):


PrimitiveType:

	NumericType

	boolean

NumericType:

	IntegralType

	FloatingPointType

IntegralType: one of

	byte short int long char

FloatingPointType: one of

	float double

Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that same type. The value of a variable of primitive type can be changed only by assignment operations on that variable.

The numeric types are the integral types and the floating-point types.

The integral types are byte , short , int , and long , whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char , whose values are 16-bit unsigned integers representing Unicode characters.

The floating-point types are float , whose values are 32-bit IEEE 754 floating-point numbers, and double , whose values are 64-bit IEEE 754 floating-point numbers.

The boolean type has exactly two values: true and false.


4.2.1 Integral Types and Values

The values of the integral types are integers in the following ranges:


4.2.2 Integer Operations

Java provides a number of operators that act on integral values:

Other useful constructors, methods, and constants are predefined in the classes Integer (S20.7), Long (S20.8), and Character (S20.5).

If an integer operator other than a shift operator has at least one operand of type long , then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long . If the other operand is not long , it is first widened (S5.1.2) to type long by numeric promotion (S5.6). Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int . If either operand is not an int , it is first widened to type int by numeric promotion.

The built-in integer operators do not indicate overflow or underflow in any way. The only numeric operators that can throw an exception (Chapter 11) are the integer divide operator / (S15.16.2) and the integer remainder operator % (S15.16.3), which throw an ArithmeticException if the right-hand operand is zero.

The example:


class Test {
	public static void main(String[] args) {
		int i = 1000000;
		System.out.println(i * i);
		long l = i;
		System.out.println(l * l);
		System.out.println(20296 / (l - i));
	}
}

produces the output:


-727379968
1000000000000

and then encounters an ArithmeticException in the division by l - i , because l - i is zero. The first multiplication is performed in 32-bit precision, whereas the second multiplication is a long multiplication. The value -727379968 is the decimal value of the low 32 bits of the mathematical result, 1000000000000 , which is a value too large for type int .

Any value of any integral type may be cast to or from any numeric type. There are no casts between integral types and the type boolean .


4.2.3 Floating-Point Types and Values

The floating-point types are float and double , representing the single-precision 32-bit and double-precision 64-bit format IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).

The IEEE 754 standard includes not only positive and negative sign-magnitude numbers, but also positive and negative zeros, positive and negative infinities, and a special Not-a-Number (hereafter abbreviated NaN). The NaN value is used to represent the result of certain operations such as dividing zero by zero. NaN constants of both float and double type are predefined as Float.NaN (S20.9.5) and Double.NaN (S20.10.5).

The finite nonzero values of type float are of the form , where s is +1 or -1, m is a positive integer less than , and e is an integer between -149 and 104, inclusive. Values of that form such that m is positive but less than and e is equal to -149 are said to be denormalized.

The finite nonzero values of type double are of the form , where s is +1 or -1, m is a positive integer less than , and e is an integer between -1075 and 970, inclusive. Values of that form such that m is positive but less than and e is equal to -1075 are said to be denormalized.

Except for NaN, floating-point values are ordered; arranged from smallest to largest, they are negative infinity, negative finite nonzero values, negative zero, positive zero, positive finite nonzero values, and positive infinity.

Positive zero and negative zero compare equal; thus the result of the expression 0.0==-0.0 is true and the result of 0.0>-0.0 is false . But other operations can distinguish positive and negative zero; for example, 1.0/0.0 has the value positive infinity, while the value of 1.0/-0.0 is negative infinity. The operations Math.min and Math.max also distinguish positive zero and negative zero.

NaN is unordered, so the numerical comparison operators < , <= , > , and >= return false if either or both operands are NaN (S15.19.1). The equality operator == returns false if either operand is NaN, and the inequality operator != returns true if either operand is NaN (S15.20.1). In particular, x!=x is true if and only if x is NaN, and (x<y) == !(x>=y) will be false if x or y is NaN.

Any value of a floating-point type may be cast to or from any numeric type. There are no casts between floating-point types and the type boolean .


4.2.4 Floating-Point Operations

Java provides a number of operators that act on floating-point values:

Other useful constructors, methods, and constants are predefined in the classes Float (S20.9), Double (S20.10), and Math (S20.11).

If at least one of the operands to a binary operator is of floating-point type, then the operation is a floating-point operation, even if the other is integral.

If at least one of the operands to a numerical operator is of type double , then the operation is carried out using 64-bit floating-point arithmetic, and the result of the numerical operator is a value of type double . (If the other operand is not a double , it is first widened to type double by numeric promotion (S5.6).) Otherwise, the operation is carried out using 32-bit floating-point arithmetic, and the result of the numerical operator is a value of type float. If the other operand is not a float , it is first widened to type float by numeric promotion.

Operators on floating-point numbers behave exactly as specified by IEEE 754. In particular, Java requires support of IEEE 754 denormalized floating-point numbers and gradual underflow, which make it easier to prove desirable properties of particular numerical algorithms. Floating-point operations in Java do not "flush to zero" if the calculated result is a denormalized number.

Java requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest.

Java uses round toward zero when converting a floating value to an integer (S5.1.3), which acts, in this case, as though the number were truncated, discarding the mantissa bits. Rounding toward zero chooses at its result the format's value closest to and no greater in magnitude than the infinitely precise result.

Java floating-point operators produce no exceptions (Chapter 11). An operation that overflows produces a signed infinity, an operation that underflows produces a signed zero, and an operation that has no mathematically definite result produces NaN. All numeric operations with NaN as an operand produce NaN as a result. As has already been described, NaN is unordered, so a numeric comparison operation involving one or two NaNs returns false and any != comparison involving NaN returns true , including x!=x when x is NaN.

The example program:


class Test {

	public static void main(String[] args) {

		// An example of overflow:
		double d = 1e308;
		System.out.print("overflow produces infinity: ");
		System.out.println(d + "*10==" + d*10);

		// An example of gradual underflow:
		d = 1e-305 * Math.PI;
		System.out.print("gradual underflow: " + d + "\n      ");
		for (int i = 0; i < 4; i++)
			System.out.print(" " + (d /= 100000));
		System.out.println();

		// An example of NaN:
		System.out.print("0.0/0.0 is Not-a-Number: ");
		d = 0.0/0.0;
		System.out.println(d);

		// An example of inexact results and rounding:
		System.out.print("inexact results with float:");
		for (int i = 0; i < 100; i++) {
			float z = 1.0f / i;
			if (z * i != 1.0f)
				System.out.print(" " + i);
		}
		System.out.println();

		// Another example of inexact results and rounding:
		System.out.print("inexact results with double:");
		for (int i = 0; i < 100; i++) {
			double z = 1.0 / i;
			if (z * i != 1.0)
				System.out.print(" " + i);
		}
		System.out.println();

		// An example of cast to integer rounding:
		System.out.print("cast to int rounds toward 0: ");
		d = 12345.6;
		System.out.println((int)d + " " + (int)(-d));
	}
}

produces the output:


overflow produces infinity: 1.0e+308*10==Infinity
gradual underflow: 3.141592653589793E-305
	3.1415926535898E-310 3.141592653E-315 3.142E-320 0.0
0.0/0.0 is Not-a-Number: NaN
inexact results with float: 0 41 47 55 61 82 83 94 97
inexact results with double: 0 49 98
cast to int rounds toward 0: 12345 -12345

This example demonstrates, among other things, that gradual underflow can result in a gradual loss of precision.

The inexact results when i is 0 involve division by zero, so that z becomes positive infinity, and z * 0 is NaN, which is not equal to 1.0 .


4.2.5 The boolean Type and boolean Values

The boolean type represents a logical quantity with two possible values, indicated by the literals true and false (S3.10.3). The boolean operators are:

Boolean expressions determine the control flow in several kinds of statements:

A boolean expression also determines which subexpression is evaluated in the conditional ? : operator (S15.24).

Only boolean expressions can be used in control flow statements and as the first operand of the conditional operator ? : . An integer x can be converted to a boolean , following the C language convention that any nonzero value is true , by the expression x!=0 . An object reference obj can be converted to a boolean , following the C language convention that any reference other than null is true , by the expression obj!=null .

A cast of a boolean value to type boolean is allowed (S5.1.1); no other casts on type boolean are allowed. A boolean can be converted to a string by string conversion (S5.4).

Top© 1996 Sun Microsystems, Inc. All rights reserved.