HowToDoInJava

  • All Tutorials
  • Spring Boot
  • Java 8
  • Interview Questions
Home / Core Java / Java Basics / Correct way to compare floats or doubles in Java

Correct way to compare floats or doubles in Java

February 7, 2018 by Lokesh Gupta

In reality, it is not only Java specific problem. It can be observed in almost all the programming languages today. In computer memory, floats and doubles are stored using IEEE 754 standard format. How the actual storage and conversion works, it is out of scope of this article.

For now, just understand that during computations and conversions, minor rounding errors can be introduced in these numbers. That’s why it is not advisable to simply rely on the equality operators (==) to compare floating-point numbers.

Table of Contents

Simple comparison [Not recommended]
Threshold based comparison [Recommended]
Compare with BigDecimal [Recommended]

Simple comparison [Not recommended]

First look at the simple comparison to understand what exactly is wrong with simple comparisons. In given program, I am creating same floating point number (i.e. 1.1) using two methods:

i) Add .1, 11 times.
i) Multiply .1 to 11.

In theory, both operations whould produce the number 1.1. And when we compare the results of both methods, it should match.

Let’s do it.

private static void simpleFloatsComparison() {
	//Method 1
	double f1 = .0;
	for (int i = 1; i <= 11; i++) {
		f1 += .1;
	}
	//Method 2
	double f2 = .1 * 11;

	System.out.println("f1 = " + f1);
	System.out.println("f2 = " + f2);

	if (f1 == f2)
		System.out.println("f1 and f2 are equal\n");
	else
		System.out.println("f1 and f2 are not equal\n");
}

Output:

f1 = 1.0999999999999999
f2 = 1.1
f1 and f2 are not equal

Look at the both values. f1 is computed to 1.0999999999999999. Its exactly the problem which rounding off causes internally. That’s why, simple floating point comparion is not recommended.

Threshold based comparison [Recommended]

Now when we know the problem, lets solve it. Using programming, we cannot change the way these floating point numbers are stored or computed. So we have to adapt a solution where we agree that a determine the differences in both values which we can tolerate and still consider the numbers equal. This agreed upon difference in values is called the threshold.

So now to use ‘threshold based floating point comparison’, we can use the Math.abs() method to compute a difference between the two numbers and compare the difference to a threshold value.

private static void thresholdBasedFloatsComparison() {
	final double THRESHOLD = .0001;

	//Method 1
	double f1 = .0;
	for (int i = 1; i <= 11; i++) {
		f1 += .1;
	}

	//Method 2
	double f2 = .1 * 11;

	System.out.println("f1 = " + f1);
	System.out.println("f2 = " + f2);

	if (Math.abs(f1 - f2) < THRESHOLD)
		System.out.println("f1 and f2 are equal using threshold\n");
	else
		System.out.println("f1 and f2 are not equal using threshold\n");
}

Output:

f1 = 1.0999999999999999
f2 = 1.1
f1 and f2 are equal using threshold

Compare with BigDecimal [Recommended]

In BigDecimal class, you can specify the rounding mode and exact precision which you want to use. Using the exact precision limit, rounding errors are mostly solved.

Best part is that BigDecimal numbers are immutable i.e. if you create a BigDecimal BD with value “1.23”, that object will remain “1.23” and can never be changed. This class provide many methods which can be used to do numerical operations on it’s value.

You can use it’s .compareTo() method to compare to BigDecimal numbers. It ignore the scale while comparing.

a.compareTo(b);  // returns (-1 if a < b),  (0 if a == b),  (1 if a > b)
Never use the .equals() method to compare BigDecimals. That is because this equals function will compare the scale. If the scale is different, .equals() will return false, even if they are the same number mathematically.

Let’s take an example to understand this comparison.

private static void testBdEquality() 
{
	 BigDecimal a = new BigDecimal("2.00");
	 BigDecimal b = new BigDecimal("2.0");

	 System.out.println(a.equals(b)); 			// false

	 System.out.println(a.compareTo(b) == 0); 	// true
}

Now just to verify, let’s solve out original problem using BigDecimal class.

private static void bigDecimalComparison() 
{
	//Method 1
	BigDecimal f1 = new BigDecimal("0.0");
	BigDecimal pointOne = new BigDecimal("0.1");
	for (int i = 1; i <= 11; i++) {
		f1 = f1.add(pointOne);
	}

	//Method 2
	BigDecimal f2 = new BigDecimal("0.1");
	BigDecimal eleven = new BigDecimal("11");
	f2 = f2.multiply(eleven);

	System.out.println("f1 = " + f1);
	System.out.println("f2 = " + f2);

	if (f1.compareTo(f2) == 0)
		System.out.println("f1 and f2 are equal using BigDecimal\n");
	else
		System.out.println("f1 and f2 are not equal using BigDecimal\n");
}

Output:

f1 = 1.1
f2 = 1.1
f1 and f2 are equal using BigDecimal

That’s all about comparing floating point numbers in java. Share your thoughts in comments section.

Happy Learning !!

Stay Updated with Awesome Weekly Newsletter

Unsubscribe

About Lokesh Gupta

Founded HowToDoInJava.com in late 2012. I love computers, programming and solving problems everyday. A family guy with fun loving nature. You can find me on Facebook, Twitter and Google Plus.

Feedback, Discussion and Comments

  1. Srini

    February 14, 2018

    I tried this threshold value of floating number one but I am not getting both are same.
    Please have a look and correct me.

    package po;
    
    public class FloatExample {
    	static double d1=0.0;
    	static double d2=.1;
    	static double thresholdValue = 0.0001;
    	
    	private static double doubleOne(){
    		
    		for(int i=1; i<=11; i++){
    			d1=d1+.1;
    		}
    		return d1;
    	}
    	
    	private static double doubleTwo(){
    		d2=d2*11;
    		return d2;
    	}
    	
    	public static void main(String[] args) {
    		doubleOne();
    		doubleTwo();
    		if(Math.abs(doubleOne()-doubleTwo())<thresholdValue){
    			System.out.println("Both are equal");
    		}else{
    			System.out.println("Both are not equal");
    		}
    	}
    }
    

    Output:
    Both are not equal

    Reply
    • Akash

      April 21, 2018

      Its because you are using global variables. Try something like below

      private static double doubleOne(){
              double d1=0.0;
              for(int i=1; i<=11; i++){
                  d1=d1+.1;
              }
              return d1;
          }
           
          private static double doubleTwo(){
              double d2=.1;
              d2=d2*11;
              return d2;
          }
      
      Reply

Ask Questions & Share Feedback Cancel reply

Your email address will not be published. Required fields are marked *

*Want to Post Code Snippets or XML content? Please use [java] ... [/java] tags otherwise code may not appear partially or even fully. e.g.
[java] 
public static void main (String[] args) {
...
}
[/java]

Help me fight spammers. Solve this simple math. *

Search Tutorials

  • Email
  • Facebook
  • RSS
  • Twitter

Recommended

  • 10 Life Lessons
  • How to Start New Blog
  • Secure Hash Algorithms
  • Regular Expressions
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices
  • Java Interview Questions
  • Microservices Tutorial
  • REST API Tutorial

Java Tutorial

  • Java – Introduction
  • Java – ClassPath
  • Java – Create Class
  • Java – main() Method
  • Java – Static Keyword
  • Java – Continue Keyword
  • Java – Break Keyword
  • Java – Transient Keyword
  • Java – Static Import
  • Java – Do-while Loop
  • Java – While Loop
  • Java – For Loop
  • Java – Enhanced Foreach Loop
  • Java – Types of Statements
  • Java – Switch Statement
  • Java – If-else Statement
  • Java – Labeled Statement
  • Java – Operators
  • Java – Data Types
  • Java – Primitive Types
  • Java – System Properties
  • Java – 32-bit vs. 64-bit
  • Java – hashCode() and equals()
  • Java – java.exe vs javaw.exe
  • Java – Generate Bytecode
  • Java – Little-Endian vs Big-Endian
  • Java – Wrapper Classes Internal Caching
  • Pass-by-Value vs. Pass-by-Reference
  • Correct way to compare floats


Developer Tools

  • JSON Formatter and Minifier
  • XML Formatter and Minifier
  • CSS Formatter and Minifier
  • HTML Formatter and Minifier

Meta Links

  • Advertise
  • Contact Us
  • Privacy policy
  • About Me

References

  • Java 8 API
  • Spring Framework Reference
  • RESTEasy Reference
  • Hibernate User Guide
  • Junit Wiki
  • Maven FAQs

Copyright © 2016 · HowToDoInjava.com · All Rights Reserved. Site hosted on Bluehost

.