Хэш-двойник в Java

Мне было интересно, как хэшировать двойник в Java? Я хешировал другие примитивные данные и объекты. Я думал, что могу использовать метод хэш-кода? Из того, что я видел, это выглядит довольно сложно. Я наткнулся на кое-что о создании семени.

Мне были интересны любые идеи о том, как это сделать. Надеетесь вставить остальную часть моего хэш-кода для класса, у которого есть двойник?

Мне было интересно, есть ли проблемы со мной, когда я пытаюсь хэшировать массивы, массивы и другие объекты в java. Некоторые из моих классов содержат массивы.

Огромное спасибо


person daveb    schedule 10.03.2012    source источник


Ответы (4)


Double.hashCode() сложный? Он в основном преобразует double в long (здесь нет никакой магии, в конце концов, они оба являются просто 64-битными значениями в памяти), а вычисление хэша long довольно просто. Преобразование double -> long выполняется с помощью public static doubleToLongBits(). Что в этом сложного?

Примеры:

Double.valueOf(42.5).hashCode();        //better answer to everything

Long.valueOf(Double.doubleToLongBits(42.5)).hashCode();
person Tomasz Nurkiewicz    schedule 10.03.2012
comment
Привет, Томаш, я попробовал хэш-код на двойном и получил следующее сообщение, которое не может быть разыменовано. Я использую метод hashcode() для getClassMethod(), т.е. this.getClassMethod().hashCode(); Метод getClassMethod возвращает значение типа double. - person daveb; 11.03.2012
comment
@daveb: взгляните на примеры, которые я только что добавил в свой ответ. - person Tomasz Nurkiewicz; 11.03.2012
comment
Спасибо @Thomasz, я сделал int hash6 = Double.valueOf(this.getClassMethod()).hashCode(); и он скомпилирован без предыдущей проблемы. Вас устраивает строка кода? Ура ДэйвБ - person daveb; 11.03.2012
comment
Короткий ответ: не используйте хэш-двойники (или числа с плавающей запятой). Хеширование чисел с плавающей запятой не даст разумных результатов из-за пределов точности. Например, [a = 1d/3d;], за которым следует [b = (a * 2 + 1) / 2 - 0.5d;], дадут вам разные ответы как двойные, даже если в идеальном мире они были бы одинаковыми. - person Phil; 10.07.2018
comment
@ Фил, я второй. Люди, попавшие на эту страницу, увидят ответ выше и воспримут его как решение, которое на самом деле сломается на практике. - person ToniAz; 22.03.2019

В зависимости от того, для чего вам это нужно, вы можете использовать очень простой подход, просто модифицируя его.

 int hash(double d) {
   return d % 71; //use a prime number here
 }

Если это просто для хранения нескольких двойников в хэше, это должно сработать. Если вы хотите распространить хеш, просто увеличьте «71».

person krico    schedule 10.03.2012
comment
Это плохой хеш, он вернет одно и то же значение для двойников, близких друг к другу. А что, если вашей программе нужны удвоения только между 0 и 1? Постоянный хэш. - person Tomasz Nurkiewicz; 11.03.2012
comment
Я хеширую все поля классов diff и переопределяю хэш-код, равенство и строку для всех моих классов. Чтобы я мог сравнивать объекты из них, а также убедиться, что объекты также уникальны. Я использовал 31 простое число и объединял хэш-коды в 1. Мой двойной код соответствует цене товара. ДэйвБ - person daveb; 11.03.2012
comment
@TomaszNurkiewicz полностью согласен! Вот почему я начал с зависимости от того, для чего вам это нужно. Если бы вы знали, что все ваши значения находятся в диапазоне от 0 до 1, вы должны использовать что-то другое. - person krico; 11.03.2012
comment
-1 это очень плохая хэш-функция. Он полностью удаляет дробную часть. Кроме того, он сопоставляет все числа только с 71 различным числом. - person fishinear; 25.07.2013
comment
@fishinear, если ты читаешь мой комментарий над своим, я с тобой согласен. - person krico; 24.09.2013

Как это делает Java, это преобразовать необработанный бит двойного числа в длинное.

// from Double.
public static long doubleToLongBits(double value) {
    long result = doubleToRawLongBits(value);
    // Check for NaN based on values of bit fields, maximum
    // exponent and nonzero significand.
    if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
          DoubleConsts.EXP_BIT_MASK) &&
         (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
        result = 0x7ff8000000000000L;
    return result;
}

public int hashCode() {
    long bits = doubleToLongBits(value);
    return (int)(bits ^ (bits >>> 32));
}

Примечание. Существует много значений NaN (и двух типов), но Java рассматривает их как одинаковые.

person Peter Lawrey    schedule 11.03.2012

Этот сработал для меня

int h2 = new Double(area).hashCode();
person user1599755    schedule 08.12.2013