sle*_*ske 10 java floating-point equals hashcode
我有一个有float田地的课.例如:
public class MultipleFields {
final int count;
final float floatValue;
public MultipleFields(int count, float floatValue) {
this.count = count;
this.floatValue = floatValue;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要能够按值比较实例.现在我该如何正确实施 equals&hashCode?
通常的方式来实现equals,并hashCode是只考虑各个领域.例如,Eclipse将生成以下内容equals:
public boolean equals(Object obj) {
// irrelevant type checks removed
....
MultipleFields other = (MultipleFields) obj;
if (count != other.count)
return false;
if (Float.floatToIntBits(floatValue) != Float.floatToIntBits(other.floatValue))
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
(和类似的hashCode,基本上计算count* 31 + Float.floatToIntBits(floatValue)).
这个问题是我的FP值受到舍入错误的影响(它们可能来自用户输入,来自数据库等).所以我需要一个"宽容"的比较.
常见的解决方案是使用epsilon值进行比较(参见比较IEEE浮点数和双精度数的相等性).但是,我不太确定如何equals使用这种方法实现,并且仍然有一个hashCode与之相符的内容equals.
我的想法是永远圆定义显著数字的数量进行比较,然后这个数字在这两个数字的equals和hashCode:
long comparisonFloatValue = Math.round(floatValue* (Math.pow(10, RELEVANT_DIGITS)));
Run Code Online (Sandbox Code Playgroud)
然后如果我floatValue用comparisonFloatValuein equals和替换所有用法hashCode,我应该得到一个"宽容"的比较,这是一致的hashCode.
Jon*_*eet 11
它的一个大问题是两个浮点值仍然可以非常接近但仍然比较不相等.基本上你将浮点值的范围划分为桶 - 两个值可以非常接近,而不是在同一个桶中.想象一下你使用两个有效数字,应用截断来获得桶,例如......然后11.999999和12.000001将是不相等的,但12.000001和12.9999999尽管彼此相距很远但是相等.
不幸的是,如果你没有这样的值,你就不能因为传递性而适当地实现等于:x和y可以靠近在一起,y和z可以靠近在一起,但这并不意味着x和z是紧靠在一起.