Home/Blog/Programming/Float vs. double in Java
Home/Blog/Programming/Float vs. double in Java

Float vs. double in Java

Najeeb Ul Hassan
6 min read

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

A data type in a programming language classifies and represents data in a particular category that determines the type of values that can be stored in a variable. Different programming languages offer different data types including integers, floating-point numbers, characters, strings, and boolean numbers. In this blog, we’ll focus on floating-point numbers, more precisely on the differences between float and double.

Float vs. double: Let the competition begin
Float vs. double: Let the competition begin

The difference between float and double is in their precision. Float is a 32-bit single-precision floating-point type, whereas double is a 64-bit double-precision floating point.

However, there is more to learn about these data types, such as how are they stored? What are their use cases? And more importantly, are there any differences between float and double in Java?

The two representations of a floating-point number#

A number in a binary system consists of three parts:

  • Sign: Represents whether the number is positive or negative. It is usually represented by a bit, with 00 indicating a positive and 11 indicating a negative number.
  • Integer: Represents the whole number that appears before the decimal point.
  • Fraction: Represents the fraction that appears after the decimal point.
Representation of a number in a binary system
Representation of a number in a binary system

Fixed-point representation of a binary number uses a fixed number of bits for integer and fraction parts. Although convenient, fixed-point representation has limited precision and depends on the number of bits allocated to the fractional part.

Take an example of a 16-bit representation of 3.14163.1416 where we fix 77 bits for the integer and 88 bits for the fraction after the decimal point. The remaining 11 bit is reserved for the sign bit.

  • The sign bit will be 00 since the number is positive.
  • The integer 33 is converted into binary as 00000110000011.
  • The fraction 0.14160.1416 is converted into binary as 0010010000100100.

Another approach could be to fix the number of bits for the number and another set of bits to indicate the position of the decimal point within that number. This is called floating-point representation. We call the number without a decimal point a mantissa and the position of the decimal place an exponent. Floating-point representation is beneficial for applications in which the range of the values is large and the precision requirements are high.

Floating-point representation
Floating-point representation

Let’s continue the previous example and see how 3.14163.1416 is represented in a 16-bit floating-point representation. Considering 1010 bits for the mantissa and 55 for the exponent, the sign bit will be s=0s=0 since the number is positive. For the mantissa, we start with a binary equivalent of 3.1416=11.001001003.1416 = 11.00100100, which can be written as 11.00100100×2111.00100100 \times 2^1. Now the mantissa will be 11001001001100100100, and the exponent is a binary representation of 1=000011=00001.

Float vs. double in Java#

Having understood the concept of floating-point representation, it becomes easy to distinguish between float and double. As stated earlier in this blog, the primary contrast between float and double lies in their precision.

According to the IEEE 754 standard, a float is a 32-bit binary format, while double is a 64-bit binary format. The difference in the number of bits used for an exponent and a mantissa is summarized in the table below:

Float

Double

Sign

1

1

Exponent

8

11

Mantissa

23

52

Total

32

64

Now that we know the distribution of bits in float and double, we can determine the range of the data types — the maximum and minimum values that can be stored.

  • A float can store decimal numbers ranging from approximately ±1.5×1045\pm 1.5 \times 10^{-45} to ±3.4×1038\pm3.4 \times 10^{38}.
  • A double can store decimal numbers ranging from approximately ±5×10324\pm5 \times 10^{-324} to ±1.7×10308\pm1.7 \times 10^{308}.

Applications#

Let’s talk about some common applications in which float and double are used.

Float#

In general, applications that require less precision, are bound by processing power, or are limited by storage are suitable for using float instead of double. Some common examples of these applications are as follows:

  • Mobile devices: Storage is usually limited in mobile devices, making float an obvious choice. Float requires less memory and is more efficient at processing power than double.

  • Time-critical systems: Time-critical systems are often constrained by latency, making them an obvious use case for using float. A typical example is a self-driving car, in which faster processing and low processing latency are critical. Note that using float will make the processing faster at the expense of precision.

  • Graphics and audio processing: Since float has less precision, it’s also suitable for graphics and audio processing — applications in which it can provide enough precision.

Double#

Since double provides greater precision, the use cases are distinct compared to float. Here are some examples in which double would be suitable instead of float:

  • Financial calculations: Since precision is a key here, double is preferred in financial calculations to avoid rounding errors.

  • Scientific computing: Another use case for double is in scientific computations requiring accuracy. Examples include physics simulations, statistical simulations, climate modeling, etc.

  • Defense systems: A vital application in which precision is essential is defense systems. This is because in defense systems, like missile guiding systems, representing coordinates is critical and significantly impacts the accuracy of the results.

The diagram below briefly summarizes how to choose between a float and a double. Gauging the requirements of the underlying application can help you choose.

Spider diagram with precision, latency, and storage
Spider diagram with precision, latency, and storage

Rounding errors#

Arithmetic operations with floating-point numbers are not exact and can lead to rounding errors. These rounding errors can accumulate over time, leading to unexpected results. Let’s look at a simple example of adding a fraction=1/10 ten times in Java. Ideally, it should result in 1. Let’s see how floating-point arithmetic calculates it.

public class Main {
public static void main(String[] args) {
float exp_result = 1.0f;
float fraction = 1.0f / 10.0f;
System.out.println();
float sum = 0.0f;
for (int i = 0; i < 10; i++) {
sum += fraction;
}
System.out.println("Expected Result: " + exp_result);
System.out.println("Actual Sum : " + sum);
if (exp_result == sum)
System.out.println("The expected result is equal to the calculated result");
else
System.out.println("The expected result is not equal to the calculated result");
}
}

Here, we append f or F to the value to declare a float on lines 3–4. We define a fraction on line 4 and add this fraction ten times to the variable sum on lines 9–11 in a for loop. Finally, the expected and actual results are compared on lines 16–19.

Note: The output will not change even if we change the variable types from float to double on lines 3–4. Go ahead and try it yourself!

The output shows that the actual result is different from the expected result. This is because the rounding errors accumulate over time.

Using tolerance#

Using appropriate tolerance values instead of exact comparisons when using floating-point numbers is essential. This avoids unexpected results when comparing floating-point numbers. The choice of tolerance depends on the application and the precision required. Let’s look at how to use tolerance values in our example.

public class Main {
public static void main(String[] args) {
float exp_result = 1.0f;
float fraction = 1.0f / 10.0f;
float tolerance = 0.000001f;
System.out.println();
float sum = 0.0f;
for (int i = 0; i < 10; i++) {
sum += fraction;
}
System.out.println("Expected Result: " + exp_result);
System.out.println("Actual Sum : " + sum);
if (Math.abs(exp_result - sum) < tolerance)
System.out.println("The expected result is equal to the calculated result");
else
System.out.println("The expected result is not equal to the calculated result");
}
}

Here, we defined a variable tolerance on line 5 to compare the absolute difference between the actual and expected results on line 17. The output is now as expected.

We hope this experience was fun and helped you learn the differences between float and double in Java. If you’re looking to explore other data types and how they’re used in different programming languages, we recommend checking out the following courses on Educative:

Learn C++ from Scratch

Cover
Learn C++ from Scratch

Learn C++ for free with this interactive course, and get a handle on one of the most popular programming languages in the world. You'll start with a simple hello world program and proceed to cover core concepts such as conditional statements, loops, and functions in C++, before moving on to more advanced topics like inheritance, classes, and templates, along with much more. By the time you're done, you'll be an intermediate level C++ developer, ready to take on your own projects.

10hrs
Beginner
16 Challenges
25 Quizzes

Learn to Code: Java for Absolute Beginners

Cover
Learn to Code: Java for Absolute Beginners

Java is a high-level, object-oriented language known for its portability and reliability. Mastering Java is key for developers to build scalable, secure software efficiently. In this course, you will start by mastering the art of problem-solving with simple Java programs, such as the Bottle Filling example. You will learn how to structure your solutions, create execution sheets, and enhance your problem-solving abilities through practical exercises and quizzes. Progressing further, you will learn decision-making and branching in Java, understanding flowcharts, conditional expressions, and their application. You will also learn about Java basics, including the first Java program, fundamentals, conditional statements, and error categories, followed by in-depth lessons on working with Java strings and arrays. By the end of this course, you will have a solid understanding of Java programming fundamentals and the ability to solve real-world problems using Java.

8hrs
Beginner
4 Challenges
6 Quizzes

Python 3: From Beginner to Advanced

Cover
Python 3: From Beginner to Advanced

In this course, you will get a comprehensive overview of Python. You will start by laying the foundation and learning the introductory topics like operators, conditional statements, functions, loops, assignment statements, and more. You will then move onto more advanced topics such as classes and inheritance, iterators, list comprehensions, and dictionaries. Along with this, you will also get to explore the concept of testing and take a look at how GUI applications can be designed using Tkinter, Python's standard GUI library. By the time you're done, you'll be able to hit the ground running and be equipped with the tools that will allow you to be productive in Python.

4hrs
Beginner
7 Challenges
7 Quizzes

  

Free Resources