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.
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?
A number in a binary system consists of three parts:
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 where we fix bits for the integer and bits for the fraction after the decimal point. The remaining bit is reserved for the sign bit.
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.
Let’s continue the previous example and see how is represented in a 16-bit floating-point representation. Considering bits for the mantissa and for the exponent, the sign bit will be since the number is positive. For the mantissa, we start with a binary equivalent of , which can be written as . Now the mantissa will be , and the exponent is a binary representation of .
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.
Let’s talk about some common applications in which float and double are used.
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.
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.
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");elseSystem.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
todouble
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 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");elseSystem.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
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.
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.
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.
Free Resources