Creating a HashSet for Doubles

I want to create HashSetfor real numbers (currently Doubles) using a certain tolerance ( epsilon), (cf Since use only works for exact equality, and this is the last class, I cannot use it. My initial idea is to extend (for example, before ), using the method and create a new class where it uses this value from .. However, I would like to check if existing solutions and existing F / OSS libraries exist.Assert.assertEquals(double, double, double)
Double.equals()DoubleHashSetDoubleHashSetsetEpsilon(double)ComparableDoubleequals()DoubleHashSet

(In the future I will want to extend this to tuples of real numbers - for example, rectangles and cubes - so the preferred general approach is

NOTE. @NPE suggested that this is not possible. Unfortunately, I suspect that this is formally correct :-) So I wonder if there are approximate methods ... Others must have had this problem and it was solved approximately. (I already use the tool regularly Real.isEqual(a, b, epsilon), and it is very useful.) I am ready to accept some infrequent transitivity errors.

NOTE. I will use TreeSet as it solves the problem of "almost equals ()". Later I will compare complexNumbers, rectangles (and more complex objects), and it is really useful to set a limit within which 2 things are equal. There is no simple natural ordering of complexNumbers (perhaps Cantor’s work will work), but we can tell how nearly they are equal.

+5
3

.

HashSet equals() . equals() :

: x, y z, x.equals(y) true y.equals(z) true, x.equals(z) true.

:

x = 0.0
y = 0.9 * epsilon
z = 1.8 * epsilon

, (x y y z, x z). HashSet .

, hashCode() - :

equals(Object), hashCode .

hashCode() , TreeSet HashSet.

+4

, , - ( , )

.

public static double roundByFactor(double d, long factor) {
    return (double) Math.round(d * factor) / factor;
}

TDoubleHashSet set = new TDoubleHashSet(); // more efficient than HashSet<Double>
set.add(roundByFactor(1.001, 100));
set.add(roundByFactor(1.005, 100));
set.add(roundByFactor(1.01, 100));
// set has two elements.

DoubleHashSet. , HashMap TDoubleDoubleHashMap, , - .

+1

@NPE ( / , / :-)

//Create a comparator:
public class RealComparator implements Comparator<Double> {

    private double epsilon = 0.0d;

    public RealComparator(double eps) {
        this.setEpsilon(eps);
    }

    /**
     * if Math.abs(d0-d1) <= epsilon  
     * return -1 if either arg is null
     */
    public int compare(Double d0, Double d1) {
        if (d0 == null || d1 == null) {
            return -1;
        }
        double delta = Math.abs(d0 - d1);
        if (delta <= epsilon) {
            return 0;
        }
        return (d0 < d1) ? -1 : 1;
    }

    /** set the tolerance
     * negative values are converted to positive
     * @param epsilon
     */
    public void setEpsilon(double epsilon) {
        this.epsilon = Math.abs(epsilon);
    }

public final static Double ONE = 1.0;
public final static Double THREE = 3.0;

@Test
public void testTreeSet(){
    RealComparator comparator = new RealComparator(0.0);
    Set<Double> set = new TreeSet<Double>(comparator);
    set.add(ONE);
    set.add(ONE);
    set.add(THREE);
    Assert.assertEquals(2, set.size());
}
@Test
public void testTreeSet1(){
    RealComparator comparator = new RealComparator(0.0);
    Set<Double> set = new TreeSet<Double>(comparator);
    set.add(ONE);
    set.add(ONE-0.001);
    set.add(THREE);
    Assert.assertEquals(3, set.size());
}
@Test
public void testTreeSet2(){
    RealComparator comparator = new RealComparator(0.01);
    Set<Double> set = new TreeSet<Double>(comparator);
    set.add(ONE);
    set.add(ONE - 0.001);
    set.add(THREE);
    Assert.assertEquals(2, set.size());
}
@Test
public void testTreeSet3(){
    RealComparator comparator = new RealComparator(0.01);
    Set<Double> set = new TreeSet<Double>(comparator);
    set.add(ONE - 0.001);
    set.add(ONE);
    set.add(THREE);
    Assert.assertEquals(2, set.size());
}
0

All Articles