У меня есть класс с полем float
.Например:
public class MultipleFields {
final int count;
final float floatValue;
public MultipleFields(int count, float floatValue) {
this.count = count;
this.floatValue = floatValue;
}
}
Мне нужно иметь возможность сравнивать экземпляры по значению.Теперь, как правильно реализовать 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;
}
(и аналогичный hashCode
, который по существу вычисляет count* 31 + Float.floatToIntBits(floatValue)
).
Проблема в том, что мои значения FPподвержены ошибкам округления (они могут исходить из пользовательского ввода, из БД и т. д.).Поэтому мне нужно «толерантное» сравнение.
Распространенным решением является сравнение с использованием значения эпсилона (см., Например, Сравнение IEEE-чисел с плавающей запятой и двойных для равенства ).Тем не менее, я не совсем уверен, как я могу реализовать equals
, используя этот метод, и все еще есть hashCode
, который соответствует equals
.
Моя идея состоит в том, чтобы определить количество значащих цифр для сравнения, затем всегда округлять до этого количества цифр как equals
, так и hashCode
:
long comparisonFloatValue = Math.round(floatValue* (Math.pow(10, RELEVANT_DIGITS)));
Тогда, если я заменюпри всех применениях floatValue
с comparisonFloatValue
в equals
и hashCode
я должен получить «толерантное» сравнение, которое соответствует hashCode
.
- Будет ли это работать?
- Видите ли вы какие-либо проблемы с этим подходом?
- Есть ли лучший способ сделать это?Это кажется довольно сложным.