Deep Dive into float and double data types in Java

Hello All, float and double are two fo the important data types in Java, but many developers don't pay enough attention to these two data types, resulting in writing poor code with subtle bugs. To be honest, they are not easy to use because of the complexity with floating-point calculation but knowing even simple things like the maximum, and minimum limit of float and double data types and how to compare float and double variables can go a long way in eliminating bugs which are not obvious. All this information is available on Java documentation and books and courses I have shared earlier, but by writing this article, I am bringing all this information in one place, which will help you to learn and remember them better.


The float and double data type Deep Dive in Java

Without wasting any more of your time, let's just dive into the float and double data types:

1) Both float and double data types are mainly provided for scientific and engineering calculations. Java uses binary floating-point calculations, which are suitable for approximation but doesn't give an exact result.  The bottom line is, don't use float/double when an accurate calculation is needed.

You cannot represent values like 0.1 or 0.01 or any negative power of 10 accurately in Java. Calculating interest, expenses is one example of this. I also suggest going through a comprehensive Java course like The Complete Java Masterclass to learn more about Java data types in depth. It's one of the must-know things for every Java developer.



2) Don't use float and double on the financial calculation, instead prefer BigDecimal. If you have to use float, then limit the precision like 8 places up to the decimal point.

3) Don't compare float and double using == operator, Instead use > or < you may be wondering why? Well,  if you use == with float/double as loop terminating condition, then this may result in an endless loop because a float/double may not be precisely equal to sometimes as Java uses binary floating-point calculation, which results in approximation.

Instead of checking  floatingPointNumber == 10.10 check floatingPointerNumber > 10.09 or floatingPointerNumber < 10.09

For more detail, see Why you should not compare double/float using == in Java.

4) float and double both are primitive data types in Java. Float uses 32 bits to store data, while double uses 64 bits to store data.

5) While using float and double in hashCode() method, use them as long, as suggested in Effective Java, for example Double.longBits() or Float.longBits()

best Java book for developers



6) By default result of an integer, the calculation is int, and a floating-point calculation is double in Java. If an expression involves both double and int then the result will always be double, as shown in below example

double ten = 10.00;
int nine = 9;  
// int result = ten*nine;  // compile time error, need casting because result is double
double result = ten * nine; //Ok

7) by default any floating-point number (number with a decimal point )is double in Java if you want to store floating-point number as a float then use suffix for F or cast it into a float, as shown in the following example

double d = 2.00; // by default double
float  f = 2.00; // type mismatch: cannot convert from double to float
float  f1 = (float) 2.00; // OK
float  f2 = 2.00f ; // Ok



8) The program often confuses between Maximum and Minimum values of double and float; unlike to int and long, they cannot be calculated based upon the size of float and double in bits, e.g., 32 and 64. That's why the maximum value of long can be stored in float without any casting, but you cannot store a float value in long without casting, as displayed in the following example:

double maxDouble = Double.MAX_VALUE;
double minDouble = Double.MIN_VALUE;  
float  maxFloat = Float.MAX_VALUE;
float  minFloat = Float.MIN_VALUE;   
 
System.out.println("Maximum value of double data type in Java : " + maxDouble);
System.out.println("Minimum value of double in Java : " + minDouble);
System.out.println("Maximum value of float data type in Java : " + maxFloat);
System.out.println("Minimum value of float in Java : " + minFloat);
 
 
float myfloat = Long.MAX_VALUE; //OK
long  myLong = Float.MAX_VALUE;  // Not Ok, Type mismatch, cannot convert from float to long
 
Output:
The maximum value of double data type in Java: 1.7976931348623157E308
The minimum value of double in Java: 4.9E-324
The maximum value of float data type in Java: 3.4028235E38
The minimum value of float in Java: 1.4E-45
 
 
9)  0.1 cannot be represented accurately as double or float values. For fun, can you write a program to produce a sum of 0.10, 100 times, and compare it with 10?

10) double is a 64-bit primitive, and Double is an Immutable class to wrap this value. Similarly, the float data type is a 32-bit primitive data type, while Float is an Immutable wrapper class. From Java 1.5 onwards, Java can automatically convert one into another; this is known as autoboxing and unboxing in Java.

11) Do you know what an "ulp" means? It's the distance between two floating-point values. "ulp" is actually short form/acronym for the unit in the last place. You can calculate ulp for float and double by using java.lang.Math class. It has ulp(double d) and ulp(float f) method for the same purpose, added on Java 1.5. Here is an example of finding ulp of float/double in Java

System.out.println("ulp for double in Java : " + Math.ulp(3.14));
System.out.println("ulp value for float in Java : " + Math.ulp(3.14f));
 
Output:
ulp for double in Java : 4.440892098500626E-16
ulp value for float in Java : 2.3841858E-7

12) You can represent infinity using float/double in Java, which may come as a surprise to you, but it’s true. Both Float and Double wrapper class have constant value to represent infinity as


  • Double.POSITIVE_INFINITY, 
  • Double.NEGATIVE_INFINITY,
  • Float.POSITIVE_INFINITY, 
  • Float.NEGATIVE_INFINITY. 

They also have a method to test, whether a double/float value is infinity or not, by using isInfinite() method, as shown in the following example:

double infinity = 1.0/0.0; // divide by zero is infinity in maths
System.out.println(Double.isInfinite(infinity));  // prints true

Remember adding a small floating-point value will not change the large floating-point value, which means adding something on infinity will also be infinity, as shown below:

double infinity = 1.0/0.0; // divide by zero is infinity in maths
infinity = infinity + 100;
System.out.println(Double.isInfinite(infinity));  // still true


There are a couple of good puzzles, based upon this concept in Java Puzzlers.

13) The result of a floating-point operation is a floating-point value that is closest to their exact mathematical result. Once the distance between adjacent floating-point values is greater than 2, adding 1 to a floating-point value will have no effect, like adding something into infinity always equals infinity. For the float type, the least magnitude beyond which adding 1 will have no effect is 2^25 and for double its 2^54, approximately 1.8 x 10^16.

14) Apart from their size e.g. 32 bit vs 64 bit, main difference between float and double datatype is that float values are called single precision and double values are known as double-precision, because maximum number of significant digits (number of decimal places or precision) in float is 6 or 7, while for double it's 15. Memory allocated for a float data type is 4 bytes, while memory allocated for a double data type is 64 bit.

15) To represent real numbers, Java uses floating-point notation. The following table shows some examples of a floating-point number and how Java might print them. In Java, floating-point notation letter e stands for the exponent.

84.924

That's all about double and float in Java. As a Java developer, it’s important to know basics, and know it well. Actually, in-depth knowledge of basics differs from an inexperienced developer to an experienced one. Always remember Java uses binary floating-point arithmetic, which is only an approximation to real arithmetic.

Don't use == to compare float and double and avoid using float/double values in places where you need exact calculation, like monetary calculation. Prefer using BigDecimal in place of double/float values for precise results.

I think it's not just that people don't know about BigDecimal (they probably pass it in Javadoc many times), but that using BigDecimal means (1) your formulas become far more obtuse and hard to read, and (2) you can't use floating-point libraries and frameworks.

Leaving operator overloading out of Java was probably a good thing, but it makes it a bad language for finance. I'd say just use Scala, but then you'd have to spend two years learning Scala-- which is made harder because of... operator overloading.

Further Learning
Complete Java Masterclass
Java Fundamentals: The Java Language
Java In-Depth: Become a Complete Java Engineer!


Other Java Programming articles you may like
  • How to convert float to long or int in Java? (solution)
  • How do you convert String to ASCII value in Java? (answer)
  • 5 ways to convert InputStream to String in Java? (solution)
  • How do you format Date to String in Java? (answer)
  • XMLGregorianCalendar to Date in Java and Vice-versa (solution)
  • How to convert a list to Stream in Java 8? (example)
  • How do you convert Java Object to XML using JAXB? (example)
  • How to convert Fahrenheit to Celsius in Java? (program)
  • String to Date conversion in Java using SimpleDateFormat class (solution)
  • How do you convert Double to String in Java? (solution)
  • How do you convert Binary to Decimal in Java? (answer)
  • How to convert Double to Long in Java? (example)

Thanks for reading this article so far. If you like this article, then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.  If you like, you can also follow Javarevisited on Twitter, I only tweet about Java, programming, and technical stuff.

No comments:

Post a Comment