Floating Point Literals

A direct (literal) expression of a floating point value in source code.

Float literals are used to directly write a decimal value (or any float or double) in source code. Floating point literals have type double or float, depending on how they're specified.

Syntax

Floating point literals can be expressed through four forms:

1 decimal-significandfloat-suffix
2 decimal-significandexponent
3 decimal-significandexponentfloat-suffix
4 hex-significandbinary-exponentfloat-suffix

where...

decimal-significand is one or more decimal digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9), possibly with one decimal point (.) before, after, or in between any of the digits.In other words, the decimal-significand is one of:
  1. A decimal point followed by one or more decimal digits, e.g. .439,
  2. one or more decimal digits followed by a decimal point, e.g. 1., or
  3. one or more decimal digits followed by a decimal point and then one or more decimal digits, e.g. 0.3.
hex-significand is the string prefix 0x or 0X, followed by one or more hexadecimal digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, A, B, C, D, E, F), possibly with one decimal point (.) before, after, or in between any of the digits.In other words, the hex-significand is one of:
  1. 0x or 0X, followed by a decimal point, followed then by one or more hexadecimal digits, e.g. 0x.43A,
  2. 0x or 0X, followed by one or more hexadecimal digits, followed then by a decimal point, e.g. 0xfff.,
  3. 0x or 0X, followed by one or more hexadecimal digits, followed by a decimal point, followed by one or more hexadecimal digits, e.g. 0xabc.ef.
float-suffix is one of the characters f, F, d, or D.
exponent is the character e or E, possibly followed by a sign symbol (either + or -), followed by one or more decimal digits.
binary-exponent is the character p or P, possibly followed by a sign symbol (either + or -), followed by one or more decimal digits. Despite the significand of the number being expressed in hexadecimal, the binary-exponent must be specified in decimal. See Note 2 below.

such that...

Syntax Elements

1 A base-10 floating point literal using a suffix to indicate whether the literal is of type float or double.

2 A base-10 floating point literal that specifies an exponent. The literal is always of type double.

3 A base-10 floating point literal that specifies both an exponent and a suffix.

4 A base-16 floating point literal that specifies a binary exponent and, optionally, a suffix.

Interpretation

The value of a floating point literal is calculated by interpreting it as a number in scientific notation, and then rounding that number to the closest value in the value set for the literal's type. The float-suffix, when included, determines whether the literal is of type double or float, and thus determines the corresponding value set. The value set of float is the set of all values in the IEEE 754 32-bit single-precision floating-point format, and the value set for double is the set of all values in the IEEE 754 64-bit double-precision format.

Base-10 Interpretation

If the literal is in base-10 and it includes no exponent, it is simply interpreted as a base-10, possibly-fractional number. If an exponent is included, then the interpretation of the literal is the decimal-significand multiplied by 10 to the power of exponent.

Denoting the significand as s and the exponent as e, the interpretation of a base-10 floating point literal is s × 10e .

Base-16 Interpretation

If the literal is in base-16, its interpretation is the hexadecimal-significand multiplied by 2 to the power of binary-exponent. Denoting the base-16 significand as s and the base-10 exponent as p, the interpretation of the literal is s × 2p .

Restrictions on Floating Point Literals

Floating point literals' syntax do not provide a direct means of expressing negative values. A floating point literal that, upon being rounded to the closest value in its type's value set, rounds to Infinity, results in a compile-time error. Additionally, any floating point literal that rounds to 0, but is not equal to 0, results in a compile time error. This means that literals which are "too big" (e.g., 1e99f or 1e999d) or "too small" (too close to 0, e.g. 1e-99f or 1e-999d) to be represented by a float or double will raise compile-time errors. See the below example for examples.

Even if a floating point literal is too large or small to be expressed exactly as its corresponding type, so long as rounding the value of the literal to the nearest value in the value set does not result in 0 or Infinity, the literal is permitted. For example, even though the smallest actual float is approximately 1.401e-45, the literal 0.71e-45f is valid, and can be used in code:

// Use BigDecimal to print exact float value:
System.out.println(new BigDecimal(0.71e-45f));

Note, however, that the value of that float literal is rounded to the nearest value in the value set for the float type. The output of the above code is:

1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125E-45

which is the smallest representable float.

Permissible Floating Point Literals

The exact set of permissible float literals (those suffixed with f or F) is comprised of the literals exactly equal to:

The exact set of permissible double literals (those that have no suffix or have the suffix d or D) is comprised of the literals exactly equal to:

Any of the literals in the aforementioned sets can be written in a syntactically valid Java program.

Examples

Simple Usage

This example demonstrates various powers of 2 declared as base-10 and base-16 literals using exponents. Note that ^ in the comments is used to denote exponentiation.

// Print 1
System.out.println(1e0);	// 1 * 10^0	= 1
System.out.println(0x1p0);	// 1 * 2^0	= 1

// Print 2
System.out.println(2e0);	// 2 * 10^0	= 2
System.out.println(0x1p1);	// 1 * 2^1	= 2

// Print 4
System.out.println(4e0);	// 4 * 10^0	= 4
System.out.println(0x1p2);	// 1 * 2^2	= 4

// Print 8
System.out.println(8e0);	// 8 * 10^0	= 8
System.out.println(0x1p3);	// 1 * 2^3	= 8

// Print 16
System.out.println(1.6e1);	// 1.6 * 10^1	= 16
System.out.println(0x1p4);	// 1 * 2^4	= 16

// Print 32
System.out.println(3.2e1);	// 3.2 * 10^1	= 32
System.out.println(0x1p5);	// 1 * 2^5	= 32

// Print 64
System.out.println(6.4e1);	// 6.4 * 10^1	= 64
System.out.println(0x1p6);	// 1 * 2^6	= 64

// Print 128
System.out.println(1.28e2);	// 1.28 * 10^2	= 128
System.out.println(0x1p7);	// 1 * 2^7	= 128

Output:

1.0
1.0
2.0
2.0
4.0
4.0
8.0
8.0
16.0
16.0
32.0
32.0
64.0
64.0
128.0
128.0

Suffix Demonstration

This example demonstrates the effect of the suffix in a literal:

Number d = 1.4; // double value 1.4 gets autoboxed into java.lang.Double object
System.out.println(d.getClass());

Number f = 1.4f; // f suffix to denote float; float value gets autoboxed to java.lang.Float object
System.out.println(f.getClass());

Output:

class java.lang.Double
class java.lang.Float

Another demonstration, involving an overloaded function that takes either float or a double:

class X {
	void test(double input) {
		System.out.println("Double");
	}
	
	void test(float input) {
		System.out.println("Float");
	}
	
	void runTest() {
		test(0.0); // Prints "Double"
		test(0.0d); // Prints "Double"
		test(0.0f); // Prints "Float"
	}
}

Output of calling runTest():

Double
Double
Float

Range Restrictions

This example demonstrates the upper "edge" of the set of permissible float literals:

// Invalid float; too large:
// float x = 340282356779733661637539395458142568448f; // Float value is out of range.
float y =    340282356779733661637539395458142568447.999f; // Float value is less than the upper bound; this compiles
float z =    340282356779733661637539395458142568447.9999999999999999999999f; // Aribtrarily many digits can be appended.

// System.out.println(x);
System.out.println(y);
System.out.println(z);

// Print exact textual representations of the floats
System.out.println(new BigDecimal(y));
System.out.println(new BigDecimal(z));

Output:

3.4028235E38
3.4028235E38
340282346638528859811704183484516925440
340282346638528859811704183484516925440

Notice how the the literal assigned to x is greater than the value output by the final print statements. This is due to the literals assigned to y and z being rounded to the closest valid float, which is what is output in the two final print statements.

Notes

  1. Since the float-suffix, if included, is not considered a digit, it may not have an underscore before it. For example, 0x123p+01_f is syntactically invalid. This is because f in this case is an indicator as to the type of the literal, rather than a digit that determines the literal's value.
  2. Since the characters e and E are also hexadecimal digits, when defining a floating point number in hexadecimal, p and P are used to indicate the exponent part, rather than e or E (as are used for the exponent part of decimal floating point literals).