Hash a double in Java

22,842

Solution 1

Double.hashCode() complex? It basically converts double into a long (no magic here, after all they both are simply 64-bit values in memory) and computing long hash is quite simple. The double -> long conversion is done via public static doubleToLongBits(). What is complex about this?

Examples:

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

Long.valueOf(Double.doubleToLongBits(42.5)).hashCode();

Solution 2

The way Java does it is to convert the raw bit of a double into a long.

// 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));
}

Note: There many values of NaN (and two types) but Java treats them as all the same.

Solution 3

Depending on what you need this for, you could go with a very simple approach of just mod(ing) it.

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

If it is just for storing a few doubles in a hash, this should do it. If you want to spread the hash, just increase the "71"

Solution 4

This one worked for me

int h2 = new Double(area).hashCode();
Share:
22,842

Related videos on Youtube

daveb
Author by

daveb

Updated on July 18, 2022

Comments

  • daveb
    daveb almost 2 years

    I was wondering how to hash a double in Java? I have hashed other primitive data and objects. I thought I could use the hashcode method? From what I have seen this looks quite complex. I came across something about creating a seed.

    I was wondering any ideas on how to go about this. Hoping to put in with the rest of my hashcode for the class that has the double?

    I was wondering if there are issues with me trying to hash arraylists, arrays and other objects in java. Some of my classes contain arraylists.

    Many Thanks

  • daveb
    daveb about 12 years
    Hi Tomasz, i tried the hashcode on the double and got the following message cannot be dereferenced. I am running hashcode() method on a getClassMethod() i.e this.getClassMethod().hashCode(); The getClassMethod returns the double.
  • Tomasz Nurkiewicz
    Tomasz Nurkiewicz about 12 years
    @daveb: have a look at examples I just added to my answer.
  • daveb
    daveb about 12 years
    Thanks @Thomasz, I did int hash6 = Double.valueOf(this.getClassMethod()).hashCode(); and it compiled without the previous problem. Is the line of code okay to you? Cheers DaveB
  • Tomasz Nurkiewicz
    Tomasz Nurkiewicz about 12 years
    This is a poor hash, it will return the same value for doubles close to each other. And what if your program only needs doubles between 0 and 1? Constant hash.
  • daveb
    daveb about 12 years
    I am hashing up all the fields of the diff classes, and overriding hashcode, equals and to string for all my classes. So that I can compare objects from them and also make sure that objects are unique as well. I have been using 31 prime number and concatenating the hashcodes into 1. My double is for a price of an item. DaveB
  • krico
    krico about 12 years
    @TomaszNurkiewicz totally agree! That's why I started with "depending on what you need this for". If you "knew" your values were all between 0 and 1 you should use something else.
  • fishinear
    fishinear almost 11 years
    -1 this is an extremely poor hash function. It removes the fractional part completely. And in addition, it maps all numbers onto only 71 different ones.
  • krico
    krico over 10 years
    @fishinear, if you read my comment above yours, I agree with you.
  • Phil
    Phil almost 6 years
    The short answer is "don't hash doubles (or floats)". Hashing floating point numbers will not give you reasonable results because of the limits of precision. For instance [a = 1d/3d;] followed by [b = (a * 2 + 1) / 2 - 0.5d;] will give you different answers as doubles, even though in a perfect world they would be the same.
  • ToniAz
    ToniAz about 5 years
    @Phil I second that. Folks hitting this page will see the answer above and take it as a solution where in fact it would break in practice.