Java: Check if two double values match on specific no of decimal places
Asked Answered
P

12

13

Comparing those two values shall result in a "true":

53.9173333333333  53.9173
Pralltriller answered 31/5, 2010 at 15:3 Comment(1)
Should 53.91739999999 compare equal to 53.9173? Or to 53.9174?Janiuszck
C
26

If you want a = 1.00001 and b = 0.99999 be identified as equal:

return Math.abs(a - b) < 1e-4;

Otherwise, if you want a = 1.00010 and b = 1.00019 be identified as equal, and both a and b are positive and not huge:

return Math.floor(a * 10000) == Math.floor(b * 10000);
// compare by == is fine here because both sides are integral values.
// double can represent integral values below 2**53 exactly.

Otherwise, use the truncate method as shown in Are there any functions for truncating a double in java?:

BigDecimal aa = new BigDecimal(a);
BigDecimal bb = new BigDecimal(b);
aa = aa.setScale(4, BigDecimal.ROUND_DOWN);
bb = bb.setScale(4, BigDecimal.ROUND_DOWN);
return aa.equals(bb);
Commodore answered 31/5, 2010 at 15:4 Comment(5)
Love these kind of solutions, simple and brilliant!Dinadinah
-1. @Michael is right. This solution is flawed. I'd like your explanation as to why ` System.out.println(12512310271255125d == 12512310271255124d);` prints true if double can represent integral values exactly. It's an obviously incorrect statement given the magnitudes doubles can work with. Then there's the fact that you shouldn't be using == on reference types like BigDecimal, but that's an easy fix.Ligation
Cool downvote removed. They're good solutions for most cases.Ligation
+1 for the BigDecimal, this really does what is asked, making is very maintainable. This is what should be the preferred solution until performance has shown to need improvement.Wina
(-3.17156, -3.1715) returns falseMayfair
H
17

here is the simple example if you still need this :)

public static boolean areEqualByThreeDecimalPlaces(double a, double b) {

    a = a * 1000;

    b = b * 1000;

    int a1 = (int) a;

    int b1 = (int) b;

    if (a1 == b1) {
        System.out.println("it works");
        return true;
    }

    else
        System.out.println("it doesn't work");
    return false;
Herrah answered 20/6, 2018 at 21:35 Comment(0)
D
6

Naively:

if(Math.abs(a-b) < 0.0001)

However, that's not going to work correctly for all values. It's actually impossible to get it to work as long as you're using double, because double is implemented as binary fractons and does not even have decimal places.

You'll have to convert your values to String or BigDecimal to make meaningful tests about their decimal places.

You may want to read the Floating-Point Guide to improve your understanding of how floating point values work.

Derm answered 31/5, 2010 at 15:10 Comment(1)
Doesnt that really depend on how you translate that line…? If you want to check if those values are equal up to a certain digit, you're right with the String solution, but most of the times where such a comparation will occur, you just want to know it the results are "close enough", and in those scenarios, the line is pretty right.Yancey
A
3

Apache commons has this: org.apache.commons.math3.util.Precision equals(double x, double y, double eps)

epsilon would be the distance you would allow. Looks like yours would be 1e-5?

The source-code of this method looks like it uses Math.abs as suggested in other answers.

Alleris answered 31/10, 2016 at 18:13 Comment(0)
R
1
public static boolean areEqualByThreeDecimalPlaces(double a, double b){
    if(a < 0 && b < 0) {
        double c = Math.ceil(a * 1000) / 1000;
        double d = Math.ceil(b * 1000) / 1000;
        return c == d;
    }
    if(a > 0 && b > 0){
        double c = Math.floor(a * 1000) / 1000;
        double d = Math.floor(b * 1000) / 1000;
        return c == d;
    }
    return a == b;
}
Rayford answered 31/7, 2021 at 8:52 Comment(2)
Welcome to Stackoverflow. Please explain your solution.Mitten
The method Math.floor returns the largest Double data type that is less than or equal to the argument and is equal to mathematical integer. The method Math.ceil returns the smallest Double data type that is greater than or equal to the argument and is equal to mathematical integer. That's why I used Math.ceil for negative numbers and Math.floor for positive numbers. if non of the conditions is true than numbers are equal.Rayford
K
1
public static boolean areEqualByThreeDecimalPlaces(double a, double b) {

if(a > 0 && b >0){
    return ((int)Math.floor(a * 1000) == (int)Math.floor(b * 1000));
}
else if (a < 0 && b <0) {
    return ((int)Math.ceil(a * 1000) == (int)Math.ceil(b * 1000));
}

return a==b;
}
Kashmir answered 25/11, 2022 at 4:18 Comment(0)
P
0

Thanks. I did it this way:

double lon = 23.567889;
BigDecimal bdLon = new BigDecimal(lon);
bdLon = bdLon.setScale(4, BigDecimal.ROUND_HALF_UP);

System.out.println(bdLon.doubleValue());
Pralltriller answered 31/5, 2010 at 15:20 Comment(1)
You don't have to make a new answer, just accept the correct answer.Ferullo
O
0
public static boolean areEqualBySixDecimalPlaces(double a, double b) {
        int num1 = (int) (a * 1e6);
        int num2 = (int) (b * 1e6);
        return num1 == num2;
    }

Casting up to desired digits shall be the simplest solution if you know the values

Occupation answered 29/11, 2022 at 9:41 Comment(0)
D
0

Go ahead u can have a laugh over this one!!

public static boolean areEqualByThreeDecimalPlaces(double v, double v1) {


    if((int)v == (int)v1){

        String s = ""+v;
        String s1 = ""+v1;

        s = s.substring(s.indexOf(".")+1,s.indexOf(".")+4);
        s1 = s1.substring(s1.indexOf(".")+1,s1.indexOf(".")+4);

        return s.equals(s1);
    }
    return false;
}
Darlinedarling answered 11/3, 2023 at 12:49 Comment(1)
this way we don't have to deal with the auto rounding of decimals by java :)Darlinedarling
A
0
   public class DecimalComparator 
   {
       public static boolean areEqualByThreeDecimalPlaces(double a, double b) 
       {
           double threshold = 0.001;  // This represents 1e-3 or 0.001
           double diff = Math.abs(a - b);
           return diff <threshold;
       } 
   }
Allista answered 17/8, 2023 at 13:43 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Dovev
R
-1

The solution to compare two double-digits up to three decimal places and return true or false might be:

public static boolean areEqualByThreeDecimalPlaces(double myFirstNumber , double mySecondNumber){
    if (Math.abs(myFirstNumber - mySecondNumber) < 0.0009 ){
        return true;
    } else {
        return false;
    }
}
Randarandal answered 22/5, 2021 at 14:30 Comment(1)
This is only returning false. You should replace the whole method body to return Math.abs(myFirstNumber - mySecondNumber) < 0.0009;.Candlelight
D
-1

try this one

public static boolean isItEqual(double num1, double num2){

long firstDigit = (long)(num1 * 1000);
long secondDigit = (long)(num2 * 1000);
return firstDigit == secondDigit;
}

Daytoday answered 30/11, 2023 at 13:36 Comment(2)
That doesn't work.Buckskin
This question is 13.5 years old and there are already several highly-voted answers. Are you sure that this answer is different from all of them? Why should we use this instead of what's already here?Hoberthobey

© 2022 - 2024 — McMap. All rights reserved.