IEqualityComparer<double> with a tolerance; how to implement GetHashCode?

痞子三分冷 提交于 2019-12-08 18:51:02

问题


I'm implementing a reusable DoubleEqualityComparer (with a custom tolerance: the "epsilon" constructor parameter) to ease the usage of LINQ with sequences of double. For example:

bool myDoubleFound = doubles.Contains(myDouble, new DoubleEqualityComparer(epsilon: 0.01));

What is the right way to implement GetHashCode? Here's the code:

   public class DoubleEqualityComparer : IEqualityComparer<double>, IEqualityComparer<double?>
    {
        private readonly double epsilon;

        public DoubleEqualityComparer(double epsilon)
        {
            if (epsilon < 0)
            {
                throw new ArgumentException("epsilon can't be negative", "epsilon");
            }

            this.epsilon = epsilon;
        }

        public bool Equals(double x, double y)
        {
            return System.Math.Abs(x - y) < this.epsilon;
        }

        public int GetHashCode(double obj)
        {
            // ?
        }
   }

PS: I can always return the same value (ex: GetHashCode(double obj){ return 0; }) to always force the call to Equals(double, double) method (not very performant, I know), but I remember that this solution causes problems when the comparer is used with a dictionary...


回答1:


I'm not sure using EqualityComparer is the way to go. Because compared objects are not equals.

Maybe you should consider using a simple Any clause + an utility method :

private static bool DoublesAreNearlyEquals(double d1, double d2, double epsilon = 0.01D)
{
    return System.Math.Abs(d1 - d2) < this.epsilon;
}

private void foo()
{
    var myDoubles = Getdoubles();
    var doubleToSearch = 42D;
    var result = myDoubles.Any(d=>DoublesAreNearlyEquals(d, doubleToSearch));
}



回答2:


I would throw NotSupportedException in GetHashCode so you can have your cake and eat it too. This gives you the convenience of having an IEqualityComparer in LINQ and other methods, but guarantees that any usage of GetHashCode blows up. In practice, you might find that the way you use the equality comparer never actually requires GetHashCode to be called. You might even call this class NotHashableDoubleEqualityComparer to be super clear about the limitation to callers.



来源:https://stackoverflow.com/questions/11258962/iequalitycomparerdouble-with-a-tolerance-how-to-implement-gethashcode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!