Float Class

Su Suriya Ravichandran Updated 14 Nov 2026
6 min read ·Lesson 106 of 133

float is Java's 32-bit floating-point type, and java.lang.Float is its wrapper class. A float stores numbers with a fractional part using the IEEE 754 single-precision format, giving about 7 significant decimal digits in half the memory of a double. Understanding exactly what that precision means, and when it is enough, is the key to using float correctly. Most Java code uses double instead; float has specific, valuable uses.

Declaring float Values

A decimal literal is a double by default. A float literal needs the f (or F) suffix:

float price = 9.99f;
float ratio = 0.75F;
float big = 1.5e6f;          // scientific notation: 1,500,000
float fromInt = 42;          // int widens to float automatically

float wrong = 9.99;          // compile error: possible lossy conversion from double to float
float cast = (float) 9.99;   // allowed with an explicit cast

The compiler requires the suffix or cast because converting a double to a float discards precision.

How float Stores Numbers

A float's 32 bits are divided into three parts:

 1 bit    8 bits         23 bits
[sign] [ exponent ] [  fraction (mantissa)  ]

The value is ±1.fraction × 2^exponent. With 23 stored fraction bits plus an implicit leading 1, a float has 24 bits of precision, which corresponds to roughly 7 decimal digits.

Integer.toHexString(Float.floatToIntBits(1.0f));    // "3f800000": the raw bits of 1.0f

Most decimals are approximations

Just as 1/3 cannot be written exactly in decimal, most decimal fractions cannot be written exactly in binary. The nearest float to 0.1 is slightly larger than 0.1:

float f = 0.1f;
System.out.println(f);             // 0.1
System.out.println((double) f);    // 0.10000000149011612

println shows the shortest decimal that identifies the value, so the approximation is hidden until the value is widened to double or accumulates through arithmetic.

Whole numbers lose precision above 16,777,216

A float can represent every integer up to 2²⁴ = 16,777,216. Above that, it can no longer represent every whole number:

System.out.println(16_777_216f + 1f);    // 1.6777216E7: adding 1 has no effect
System.out.println((int) 16_777_217f);   // 16777216: the literal itself rounds

The gap between adjacent representable values (the ulp, "unit in the last place") grows with the magnitude:

Math.ulp(1.0f);          // 1.1920929E-7
Math.ulp(1_000_000f);    // 0.0625: near a million, floats are spaced 1/16 apart

This is why float is unsuitable for large counters, IDs, timestamps, and money.

Constants

ConstantValueMeaning
Float.MAX_VALUE3.4028235E38Largest finite value
Float.MIN_VALUE1.4E-45Smallest positive value (not the most negative)
Float.MIN_NORMAL1.1754944E-38Smallest positive value with full precision
Float.POSITIVE_INFINITY / NEGATIVE_INFINITYInfinity / -InfinityResults of overflow or division by zero
Float.NaNNaN"Not a number," for example 0f / 0f
Float.SIZE / Float.BYTES32 / 4Size

Special Values: Infinity, NaN, and -0.0

Floating-point arithmetic never throws an exception for division by zero or overflow. It produces special values instead:

float inf = 1f / 0f;       // Infinity
float nan = 0f / 0f;       // NaN

Float.isInfinite(inf);     // true
Float.isFinite(3f);        // true
Float.isNaN(nan);          // true

NaN has unusual rules: it is not equal to anything, including itself:

System.out.println(nan == nan);           // false
System.out.println(Float.isNaN(nan));     // true: the correct test

Floating point also has a negative zero. 0.0f == -0.0f is true, but 1 / -0.0f is -Infinity.

== versus Float.compare and equals

The == operator follows IEEE 754 rules. Float.compare and Float.equals instead define a total ordering suitable for sorting and collections:

ExpressionResult
nan == nanfalse
Float.compare(nan, nan)0
Float.valueOf(nan).equals(nan)true
0.0f == -0.0ftrue
Float.compare(0.0f, -0.0f)1 (positive zero is greater)

This is why Float.compare is used in comparators, and why NaN keys work in a HashMap<Float, ...> even though NaN != NaN.

Comparing float Values

Exact equality is unreliable after any arithmetic. Compare with a tolerance suited to the magnitude of the values:

float a = 0.1f + 0.2f;
boolean close = Math.abs(a - 0.3f) < 1e-6f;    // true

Whether exact equality succeeds depends on how each value happens to round. With float, 0.1f + 0.2f == 0.3f is actually true, while with double, 0.1 + 0.2 == 0.3 is false. Neither result should be relied on.

Parsing and Converting

float a = Float.parseFloat("3.14");      // 3.14
float b = Float.parseFloat("1e3");       // 1000.0
Float c = Float.valueOf("2.5");          // boxed
String s = Float.toString(3.14f);        // "3.14"
double d = 3.14f;                        // widening: 3.140000104904175
int i = (int) 3.99f;                     // 3: truncated toward zero
int r = Math.round(3.5f);                // 4: Math.round(float) returns int

parseFloat throws NumberFormatException for invalid text. Widening a float to double is automatic and exact, but it exposes the float's approximation as extra digits.

float or double?

Considerationfloatdouble
Precision~7 significant digits~15–16 significant digits
Range±3.4 × 10³⁸±1.8 × 10³⁰⁸
Memory4 bytes8 bytes
Default for decimal literalsNo (needs f)Yes
Arithmetic speed on modern CPUsSimilarSimilar

Use double by default: it is Java's default floating-point type, every Math method uses it, and its extra precision prevents many accuracy problems.

Use float when memory or bandwidth dominates and 7 digits are enough:

  • Large arrays of measurements, coordinates, or pixel values (a million floats take about 4 MB instead of 8 MB).
  • Graphics and game engines, and GPU APIs that expect 32-bit floats.
  • Machine-learning tensors and embeddings.
  • File formats or network protocols defined with 32-bit floats.

Use neither for money: use BigDecimal or integer amounts in the smallest currency unit.

Practical Example: Accumulated Rounding Error

A sensor reports 0.1 units ten million times. The program sums the readings with float and with double.

public class Fl {
    public static void main(String[] args) {
        int readings = 10_000_000;
        float floatSum = 0f;
        double doubleSum = 0.0;
        for (int i = 0; i < readings; i++) {
            floatSum += 0.1f;
            doubleSum += 0.1;
        }
        System.out.println("Expected:   " + readings * 0.1);
        System.out.println("float sum:  " + floatSum);
        System.out.println("double sum: " + doubleSum);

        float[] big = new float[1_000_000];
        System.out.println(big.length * Float.BYTES / 1024 + " KB vs " + big.length * Double.BYTES / 1024 + " KB");
    }
}

Output:

Expected:   1000000.0
float sum:  1087937.0
double sum: 999999.9998389754
3906 KB vs 7812 KB

The float total is off by nearly 88,000, about 9%. Two effects combine. First, 0.1f is not exactly 0.1. More importantly, as the running total grows, the gap between representable floats grows too: near one million, floats are spaced 0.0625 apart, so adding 0.1 is rounded to a multiple of 0.0625 each time, and the error compounds over millions of additions. The double sum also accumulates error, but its 53 bits of precision keep it within a tiny fraction of the expected value. The last line shows float's advantage: a million values take half the memory. The lesson is to use float for storing large amounts of moderate-precision data, and double for accumulating and computing.

0 Comments

Reviewed before they appear

No comments yet.

Java
Java Introduction Java Features Java Syntax Java Comments Java Statements Java Output Java Variables Java Data Types Java Type Casting Java Operators Java Strings Java Numbers Java Math Java Booleans Java User Input Java Conditions Java If Else Java Switch Java While Loop Java For Loop Java Break Java Continue Java Arrays Java Methods Java Parameters Java Return Values Java Scope Java Recursion Install Java Install JDK Java IDEs Java JDK Java JRE Java JVM Java Compiler Java File Compile Java Run Java JShell Basics Java Packages Java OOP Java Classes Java Objects Class Methods Constructors Constructor Overload this Keyword static Keyword final Keyword Encapsulation Inheritance Polymorphism Abstraction Access Modifiers super Keyword Method Overload Method Override Instanceof Operator Nested Classes Inner Classes Anonymous Classes Enums Records Array Basics Array Length Loop Arrays Multidimensional Arrays Array Copy Array Sorting Array Search ArrayList LinkedList HashSet TreeSet HashMap TreeMap Queue Interface Deque Interface Stack Class Iterator List Interface Set Interface Map Interface Collections Class Comparable Comparator Generics Basics Generic Classes Generic Methods Wildcards String Basics String Length String Methods String Concatenation String Compare String Search String Replace String Split String Format StringBuilder StringBuffer Text Blocks Regular Expressions Number Types Integer Class Float Class Double Class BigInteger BigDecimal Math Class Random Numbers Number Format Date Basics LocalDate LocalTime LocalDateTime ZonedDateTime Date Formatting Date Parsing Period Class Duration Class Java Instant Class Java Exception Basics Java try...catch Java Multiple Catch Blocks Java finally Block Java throw Keyword Java throws Keyword Java Checked Exceptions Java Unchecked Exceptions Java Custom Exceptions Java try-with-resources Java Exception Chaining
Ask about this post
AI Ask about this post

Ask questions about Float Class and get answers drawn from it.

Signed-in readers only.