Hash Codes for Floats in Java - java

I have a class with two float variables and hashCode method (without equals in current code snippet):
public class TestPoint2D {
private float x;
private float z;
public TestPoint2D(float x, float z) {
this.x = x;
this.z = z;
}
#Override
public int hashCode() {
int result = (x != +0.0f ? Float.floatToIntBits(x) : 0);
result = 31 * result + (z != +0.0f ? Float.floatToIntBits(z) : 0);
return result;
}
}
The following test
#Test
public void tempTest() {
TestPoint2D p1 = new TestPoint2D(3, -1);
TestPoint2D p2 = new TestPoint2D(-3, 1);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
returns same values:
-2025848832
In this case I can't use my TestPoint2D within HashSet / HashMap
Can anyone suggest how to implement hashCode in this case or workarounds related to this?
P.S.
Added one more test:
#Test
public void hashCodeTest() {
for (float a = 5; a < 100000; a += 1.5f) {
float b = a + 1000 / a; // negative value depends on a
TestPoint3D p1 = new TestPoint3D(a, -b);
TestPoint3D p2 = new TestPoint3D(-a, b);
Assert.assertEquals(p1.hashCode(), p2.hashCode());
}
}
And it is passed that proves that
TestPoint2D(a, -b).hashCode() == TestPoint2D(-a, b).hashCode()

I would use Objects.hash():
public int hashCode() {
return Objects.hash(x, z);
}
From the Javadoc:
public static int hash(Object... values)
Generates a hash code for a sequence of input values. The hash code is generated as if all the input values were placed into an array, and that array were hashed by calling Arrays.hashCode(Object[]).
This method is useful for implementing Object.hashCode() on objects containing multiple fields. For example, if an object that has three fields, x, y, and z, one could write:

These auto-generated hashcode functions are not very good.
The problem is that small integers cause very "sparse" and similar bitcodes.
To understand the problem, look at the actual computation.
System.out.format("%x\n", Float.floatToIntBits(1));
System.out.format("%x\n", Float.floatToIntBits(-1));
System.out.format("%x\n", Float.floatToIntBits(3));
System.out.format("%x\n", Float.floatToIntBits(-3));
gives:
3f800000
bf800000
40400000
c0400000
As you can see, the - is the most significant bit in IEEE floats. Multiplication with 31 changes them not substantially:
b0800000
30800000
c7c00000
47c00000
The problem are all the 0s at the end. They get preserved by integer multiplication with any prime (because they are base-2 0s, not base-10!).
So IMHO, the best strategy is to employ bit shifts, e.g.:
final int h1 = Float.floatToIntBits(x);
final int h2 = Float.floatToIntBits(z);
return h1 ^ ((h2 >>> 16) | (h2 << 16));
But you may want to look at Which hashing algorithm is best for uniqueness and speed? and test for your particular case of integers-as-float.

according to the java specification, 2 objects can have the same hashCode and this doesnt mean they are equal...
the probability is small but exist...
on the other hand is always a good practice to override both equals and hashcode...

As I understand the problem, you expect a lot of symmetrical pairs of points among your keys, so you need a hashCode method that does not tend to give them the same code.
I did some tests, and deliberately giving extra significance to the sign of x tends to map symmetrical points away from each other. See this test program:
public class Test {
private float x;
private float y;
public static void main(String[] args) {
int collisions = 0;
for (int ix = 0; ix < 100; ix++) {
for (int iz = 0; iz < 100; iz++) {
Test t1 = new Test(ix, -iz);
Test t2 = new Test(-ix, iz);
if (t1.hashCode() == t2.hashCode()) {
collisions++;
}
}
}
System.out.println(collisions);
}
public Test(float x, float y) {
super();
this.x = x;
this.y = y;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (x >= 0) ? 1 : -1;
result = prime * result + Float.floatToIntBits(x);
result = prime * result + Float.floatToIntBits(y);
return result;
}
// Equals omitted for compactness
}
Without the result = (x >= 0) ? 1 : -1; line it is the hashCode() generated by Eclipse, and counts 9802 symmetrical point collisions. With that line, it counts one symmetrical point collision.

Related

Method that takes a Point object as a parameter and returns true or false depending on whether this is within the straight section or not

I have an exercise about classes: One method says that: Takes a Point object as a parameter and returns true or false depending on whether this is within the straight section or not. A simple way to find out whether a point A is within the straight section defined by the points B, C is to check that the length of BC is equal to the sum of the lengths of BA, AC.
To avoid inaccuracies due to the representation of double numbers instead of exact equality between two quantities we check if the absolute value of their difference is quite "small".
For this method, check that the absolute value of the difference is less than 0.01 (so quantities are considered equal).
I understand that when we want to compare two quantities a, b and there is a problem of accuracy, then instead of checking if a == b we check if | a-b | <= a small number
| A-b | is the absolute value of their difference. For example, if BC is 19.456, BA + AC is 19.457 then we calculate | 19.456-19.457 | which is 0.001. If this difference is small enough to be considered negligible, then we say that the quantities are "equal".
How can I implement that?
Here is a java class that solves it :)
public class Point {
public static final double DISTANCE_TOLERANCE = 0.1;
private final double x;
public double getX() { return this.x; }
private final double y;
public double getY() {return this.y; }
public Point(final double x, final double y) {
this.x = x;
this.y = y;
}
public double getDistanceWithOtherPoint(final Point other) {
return Math.sqrt(Math.pow(this.getX() - other.getX(), 2) + Math.pow(this.getY() - other.getY(), 2));
}
public boolean isPointInTheSameLineAs(final Point b, final Point c) {
final double distanceFromThisToB = this.getDistanceWithOtherPoint(b);
final double distanceFromThisToC = this.getDistanceWithOtherPoint(c);
final double distanceBetweenBandC = b.getDistanceWithOtherPoint(c);
return Math.abs( (distanceFromThisToB + distanceFromThisToC) - distanceBetweenBandC) <= DISTANCE_TOLERANCE;
}
public static void main(String[] args) {
Point A = new Point(5.1,3.2);
Point B = new Point(7.5,2.7);
Point C = new Point(9.3,4.8);
System.out.println("Is Point A in the same line segment as B and C? " + A.isPointInTheSameLineAs(B, C));
}
}

Custom Java public key generation (Bitcoin)

A private key is random generated and it is not correlated with any wallet.
I want to prepare custom (naive) implementation of public key generation for a Bitcoin. However, after a few attempts my results was incorrect. I compared them with online generators. I've recognized I used division instead of modinv. Unfortunately, after changing division into modinv I got "java.lang.ArithmeticException: BigInteger not invertible.". I tired to follow https://www.mobilefish.com/services/cryptocurrency/cryptocurrency.html#refProdedure and https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication Could you help me recognize where I did a mistake?
public class ECDSAUtils {
private static final CurvePoint G = new CurvePoint(new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16), new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16));
private static CurvePoint zero;
private static BigInteger base;
private static final BigInteger three = new BigInteger("3", 10);
public static void main(String[] args){
ECDSAUtils e = new ECDSAUtils();
BigInteger privateKey = new BigInteger("fdc668381ab251673ef8552851a2c7cf346a6e09ea86be0f55a94d2a12253557", 16);
CurvePoint r = e.mult(G, privateKey);
System.out.println(r.x.toString(16).toUpperCase() + " " + r.y.toString(16).toUpperCase());
}
public ECDSAUtils(){
zero = new CurvePoint(new BigInteger("0", 16), new BigInteger("0", 16));
base = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
}
public static CurvePoint add(CurvePoint p, CurvePoint q){
CurvePoint result = null;
if (p.equals(zero)){
result = q;
} else if (q.equals(zero)){
result = p;
} else {
BigInteger lambda = q.y.subtract(p.y).modInverse(q.x.subtract(p.x)).mod(base);
BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(q.x).mod(base);
BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
result = new CurvePoint(x, y);
}
return result;
}
public static CurvePoint doublePoint(CurvePoint p){
BigInteger lambda = p.x.multiply(p.x).multiply(three).modInverse(p.y.add(p.y)).mod(base);
BigInteger x = lambda.multiply(lambda).subtract(p.x).subtract(p.x).mod(base);
BigInteger y = lambda.multiply(p.x.subtract(x)).subtract(p.y).mod(base);
return new CurvePoint(x, y);
}
public CurvePoint mult(CurvePoint N, BigInteger p) {
CurvePoint Q = zero;
//EDIT:
for (int i = p.bitLength() - 1; i > -1; i --) {
if (p.testBit(i)) {
Q = add(Q, N);
}
N = doublePoint(N);
}
return Q;
}
}
public class CurvePoint {
BigInteger x;
BigInteger y;
public CurvePoint(BigInteger x, BigInteger y) {
this.x = x;
this.y = y;
}
}
Exception in thread "main" java.lang.ArithmeticException: BigInteger not invertible.
at java.math.MutableBigInteger.mutableModInverse(MutableBigInteger.java:1986)
at java.math.BigInteger.modInverse(BigInteger.java:3154)
at naive.ECDSAUtils.doublePoint(ECDSAUtils.java:41)
at naive.ECDSAUtils.mult(ECDSAUtils.java:51)
at naive.ECDSAUtils.main(ECDSAUtils.java:15)
Currently the expression
is coded as follows:
y.modInverse(x).mod(p)
This is wrong and causes the observed error message. The following applies:
which must be coded as follows:
y.multiply(x.modInverse(p)).mod(p)
In the add method, the case:
is not handled. Here, the add method must return zero (i.e. the point representing the point at infinity). Geometrically, this case corresponds to a vertical secant (2 intersections).
Analogously, the case
is not handled in the doublePoint method. Here, the doublePoint method must return zero as well. Geometrically, this case corresponds to a vertical tangent (1 intersection).
The mult method doesn't work. But with regard to the comment in the code this is probably known.
Testing is easier if a small prime finite field is used. Here you can specify elliptical curves and determine the corresponding points. Note, that a curve with b != 0 must be used, otherwise the point (0,0) is a regular point of the curve and could not be used as a representative of the point at infinity.

Pointers and if statement error, in C code while converting in Java

I am trying to convert a C code to java, it's the Newton Raphson algorithm implementation. All is going well but there is a problem of pointers which were used in C code and i have removed them in java. The C code part is:
x = newton(x_0, error, max_iters, &iters, &converged); //Call to a function (newton)
if (converged) {
printf("Newton algorithm converged after %d steps.\n", iters);
printf("The approximate solution is %19.16e\n", x);
printf("f(%19.16e) = %19.16e\n", x, f(x));
} else
{
printf("Newton algorithm didn't converge after %d steps.\n",
iters);
printf("The final estimate was %19.16e\n", x);
printf("f(%19.16e) = %19.16e\n", x, f(x));
}
and the function definition is something like this:
double newton(double x_0, double error, int max_iters,
int* iters_p, int* converged_p)
Now the problem is that, the values of two pointer variables are just zero every time. Also the if(converged) shows an error message of incomoatible types. required boolean, found int. Below is the java code so please help overcome this.
//Member Functions///////
public
double function( double x)
{
return x*x - 2;
}
double F_Deriv( double x )
{
return 2.0*x;
}
double newton(double x_0, double error, int max_iters,int iters, int converged)
{
double x = x_0;
double x_prev;
int iter = 0;
do {
iter++;
x_prev = x;
x = x_prev - function(x_prev)/F_Deriv(x_prev);
}
while (Math.abs(x - x_prev) > error && iter < max_iters);
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
iters = iter;
return x;
}
/////Main Function///////
public static void main(String[] args) {
Newton_Raphson obj=new Newton_Raphson();
Scanner input=new Scanner(System.in);
double x_0; /* Initial guess */
double x; /* Approximate solution */
double error; /* Maximum error */
int max_iters; /* Maximum number of iterations */
int iters; /* Actual number of iterations */
int converged; /* Whether iteration converged */
System.out.println( "Enter Initial Solution: " );
x_0=input.nextDouble();
System.out.println( "Enter Error: " );
error=input.nextDouble();
System.out.println( "Enter Maximum Iterations: " );
max_iters=input.nextInt();
x = obj.newton(x_0, error, max_iters, iters, converged);
if(converged)
{
System.out.println("Newton algorithm converged after "+ iters +" steps.");
System.out.println("The approximate solution is "+ x);
}
else
{
System.out.println("Newton algorithm didn't converge after " + iters + " steps.");
System.out.println("The final estimate was " + x);
}
}
Java passes arguments by value, so
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
iters = iter;
doesn't change the passed arguments for the caller. These changes never leave the called function.
The simplest way to mimick out-parameters, resp. passed pointers in C, is to pass a one-length array,
double newton(double x_0, double error, int[] max_iters,int iters, boolean[] converged)
and set (and query) iters[0] resp. converged[0].
One problem is that this statement:
if (Math.abs(x - x_prev) <= error)
converged = 1;
else
converged = 0;
is not doing anything because Java is pass by value. So it won't affect the value of converged outside the method. You could instead return an object from your method which would contain 2 members: x and converged:
return new NewtonResult (x, iters, converged);
with NewtonResult defined as:
public class NewtonResult {
int x;
int iters;
boolean converged;
NewtonResult (int x, int iters, boolean converged) {
this.x = x;
this.iters = iters;
this.converged = converged;
}
}
Another problem in your code is that Java if requires a boolean when you are passing an int, so you need to change your condition to:
if (converged != 0) {
//
}
or even better make converged be a boolean.
The problem is that converged and iters are returned from the original C code. The use of pointers for those parameters is so that the parameters can mimic out semantics. Since Java only supports pass by value, you cannot return that information in the same way using plain method parameters.
The other issue is that older versions of C do not have a boolean type and so int is used instead. The flag to indicate convergence should be a boolean in Java.
So your code needs to return three pieces of information: the result (a floating point value), converged (a boolean value) and iters (an integer). You should wrap these up into an object and return them that way.
The class you need would look like this:
public class NewtonResult {
public boolean converged;
public double value;
public int iters;
}
You should change your newton method signature to be like so:
NewtonResult newton(double x_0, double error, int max_iters)
Finally, I think that tolerance would be a much better name than error for that parameter.
The class declaration is missing (public class Newton_Raphson...).
As said above, Java does not support arguments passed by reference, only by value, so you will need to wrap all those in a "Result" class.
public class Result {
public int x;
public int iters;
public int converged; // better replace this with a boolean in Java
}
and change the return type of your method to that Result class.
You cannot test an int as a boolean. You should test that it is different from 0 (since in C everything different than 0 is considered as true). Or consider using a boolean directly, it's much easier.
When passing premitive types such as int, boolean- in java as method parameters and changing them, in reality they will not be changed.
The parmeters passed are the copy of the real ones (they are actually being passed by value).
Initialize objects out of the varaiables and then pass them to the methods as:
Integer[] a = new Integer[1]; // For int a
Boolean[] b = new Boolean[1]; // For boolean b
a[0] = 1;
b[0] = true;
This way the copy of the reference of the passed object will be passed, and when you change the value of one of its elements like [0] above, it will be also changed in the real variable.

Java: simplest integer hash

I need a quick hash function for integers:
int hash(int n) { return ...; }
Is there something that exists already in Java?
The minimal properties that I need are:
hash(n) & 1 does not appear periodic when used with a bunch of consecutive values of n.
hash(n) & 1 is approximately equally likely to be 0 or 1.
HashMap, as well as Guava's hash-based utilities, use the following method on hashCode() results to improve bit distributions and defend against weaker hash functions:
/*
* This method was written by Doug Lea with assistance from members of JCP
* JSR-166 Expert Group and released to the public domain, as explained at
* http://creativecommons.org/licenses/publicdomain
*
* As of 2010/06/11, this method is identical to the (package private) hash
* method in OpenJDK 7's java.util.HashMap class.
*/
static int smear(int hashCode) {
hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
return hashCode ^ (hashCode >>> 7) ^ (hashCode >>> 4);
}
So, I read this question, thought hmm this is a pretty math-y question, it's probably out of my league. Then, I ended up spending so much time thinking about it that I actually believe I've got the answer: No function can satisfy the criteria that f(n) & 1 is non-periodic for consecutive values of n.
Hopefully someone will tell me how ridiculous my reasoning is, but until then I believe it's correct.
Here goes: Any binary integer n can be represented as either 1...0 or 1...1, and only the least significant bit of that bitmap will affect the result of n & 1. Further, the next consecutive integer n + 1 will always contain the opposite least significant bit. So, clearly any series of consecutive integers will exhibit a period of 2 when passed to the function n & 1. So then, is there any function f(n) that will sufficiently distribute the series of consecutive integers such that periodicity is eliminated?
Any function f(n) = n + c fails, as c must end in either 0 or 1, so the LSB will either flip or stay the same depending on the constant chosen.
The above also eliminates subtraction for all trivial cases, but I have not taken the time to analyze the carry behavior yet, so there may be a crack here.
Any function f(n) = c*n fails, as the LSB will always be 0 if c ends in 0 and always be equal to the LSB of n if c ends in 1.
Any function f(n) = n^c fails, by similar reasoning. A power function would always have the same LSB as n.
Any function f(n) = c^n fails, for the same reason.
Division and modulus were a bit less intuitive to me, but basically, the LSB of either option ends up being determined by a subtraction (already ruled out). The modulus will also obviously have a period equal to the divisor.
Unfortunately, I don't have the rigor necessary to prove this, but I believe any combination of the above operations will ultimately fail as well. This leads me to believe that we can rule out any transcendental function, because these are implemented with polynomials (Taylor series? not a terminology guy).
Finally, I held out hope on the train ride home that counting the bits would work; however, this is actually a periodic function as well. The way I thought about it was, imagine taking the sum of the digits of any decimal number. That sum obviously would run from 0 through 9, then drop to 1, run from 1 to 10, then drop to 2... It has a period, the range just keeps shifting higher the higher we count. We can actually do the same thing for the sum of the binary digits, in which case we get something like: 0,1,1,2,2,....5,5,6,6,7,7,8,8....
Did I leave anything out?
TL;DR I don't think your question has an answer.
[SO decided to convert my "trivial answer" to comment. Trying to add little text to it to see if it can be fooled]
Unless you need the ranger of hashing function to be wider..
The NumberOfSetBits function seems to vary quite a lot more then the hashCode, and as such seems more appropriate for your needs. Turns out there is already a fairly efficient algorithm on SO.
See Best algorithm to count the number of set bits in a 32-bit integer.
I did some experimentation (see test program below); computation of 2^n in Galois fields, and floor(A*sin(n)) both did very well to produce a sequence of "random" bits. I tried multiplicative congruential random number generators and some algebra and CRC (which is analogous of k*n in Galois fields), none of which did well.
The floor(A*sin(n)) approach is the simplest and quickest; the 2^n calculation in GF32 takes approx 64 multiplies and 1024 XORs worstcase, but the periodicity of output bits is extremely well-understood in the context of linear-feedback shift registers.
package com.example.math;
public class QuickHash {
interface Hasher
{
public int hash(int n);
}
static class MultiplicativeHasher1 implements Hasher
{
/* multiplicative random number generator
* from L'Ecuyer is x[n+1] = 1223106847 x[n] mod (2^32-5)
* http://dimsboiv.uqac.ca/Cours/C2012/8INF802_Hiv12/ref/paper/RNG/TableLecuyer.pdf
*/
final static long a = 1223106847L;
final static long m = (1L << 32)-5;
/*
* iterative step towards computing mod m
* (j*(2^32)+k) mod (2^32-5)
* = (j*(2^32-5)+j*5+k) mod (2^32-5)
* = (j*5+k) mod (2^32-5)
* repeat twice to get a number between 0 and 2^31+24
*/
private long quickmod(long x)
{
long j = x >>> 32;
long k = x & 0xffffffffL;
return j*5+k;
}
// treat n as unsigned before computation
#Override public int hash(int n) {
long h = a*(n&0xffffffffL);
long h2 = quickmod(quickmod(h));
return (int) (h2 >= m ? (h2-m) : h2);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
/**
* computes (2^n) mod P where P is the polynomial in GF2
* with coefficients 2^(k+1) represented by the bits k=31:0 in "poly";
* coefficient 2^0 is always 1
*/
static class GF32Hasher implements Hasher
{
static final public GF32Hasher CRC32 = new GF32Hasher(0x82608EDB, 32);
final private int poly;
final private int ofs;
public GF32Hasher(int poly, int ofs) {
this.ofs = ofs;
this.poly = poly;
}
static private long uint(int x) { return x&0xffffffffL; }
// modulo GF2 via repeated subtraction
int mod(long n) {
long rem = n;
long q = uint(this.poly);
q = (q << 32) | (1L << 31);
long bitmask = 1L << 63;
for (int i = 0; i < 32; ++i, bitmask >>>= 1, q >>>= 1)
{
if ((rem & bitmask) != 0)
rem ^= q;
}
return (int) rem;
}
int mul(int x, int y)
{
return mod(uint(x)*uint(y));
}
int pow2(int n) {
// compute 2^n mod P using repeated squaring
int y = 1;
int x = 2;
while (n > 0)
{
if ((n&1) != 0)
y = mul(y,x);
x = mul(x,x);
n = n >>> 1;
}
return y;
}
#Override public int hash(int n) {
return pow2(n+this.ofs);
}
#Override public String toString() {
return String.format("GF32[%08x, ofs=%d]", this.poly, this.ofs);
}
}
static class QuickHasher implements Hasher
{
#Override public int hash(int n) {
return (int) ((131111L*n)^n^(1973*n)%7919);
}
#Override public String toString() { return getClass().getSimpleName(); }
}
// adapted from http://www.w3.org/TR/PNG-CRCAppendix.html
static class CRC32TableHasher implements Hasher
{
final private int table[];
static final private int polyval = 0xedb88320;
public CRC32TableHasher()
{
this.table = make_table();
}
/* Make the table for a fast CRC. */
static public int[] make_table()
{
int[] table = new int[256];
int c;
int n, k;
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) != 0)
c = polyval ^ (c >>> 1);
else
c = c >>> 1;
}
table[n] = (int) c;
}
return table;
}
public int iterate(int state, int i)
{
return this.table[(state ^ i) & 0xff] ^ (state >>> 8);
}
#Override public int hash(int n) {
int h = -1;
h = iterate(h, n >>> 24);
h = iterate(h, n >>> 16);
h = iterate(h, n >>> 8);
h = iterate(h, n);
return h ^ -1;
}
#Override public String toString() { return getClass().getSimpleName(); }
}
static class TrigHasher implements Hasher
{
#Override public String toString() { return getClass().getSimpleName(); }
#Override public int hash(int n) {
double s = Math.sin(n);
return (int) Math.floor((1<<31)*s);
}
}
private static void test(Hasher hasher) {
System.out.println(hasher+":");
for (int i = 0; i < 64; ++i)
{
int h = hasher.hash(i);
System.out.println(String.format("%08x -> %08x %%2 = %d",
i,h,(h&1)));
}
for (int i = 0; i < 256; ++i)
{
System.out.print(hasher.hash(i) & 1);
}
System.out.println();
analyzeBits(hasher);
}
private static void analyzeBits(Hasher hasher) {
final int N = 65536;
final int maxrunlength=32;
int[][] runs = {new int[maxrunlength], new int[maxrunlength]};
int[] count = new int[2];
int prev = -1;
System.out.println("Run length test of "+N+" bits");
for (int i = 0; i < maxrunlength; ++i)
{
runs[0][i] = 0;
runs[1][i] = 0;
}
int runlength_minus1 = 0;
for (int i = 0; i < N; ++i)
{
int b = hasher.hash(i) & 0x1;
count[b]++;
if (b == prev)
++runlength_minus1;
else if (i > 0)
{
++runs[prev][runlength_minus1];
runlength_minus1 = 0;
}
prev = b;
}
++runs[prev][runlength_minus1];
System.out.println(String.format("%d zeros, %d ones", count[0], count[1]));
for (int i = 0; i < maxrunlength; ++i)
{
System.out.println(String.format("%d runs of %d zeros, %d runs of %d ones", runs[0][i], i+1, runs[1][i], i+1));
}
}
public static void main(String[] args) {
Hasher[] hashers = {
new MultiplicativeHasher1(),
GF32Hasher.CRC32,
new QuickHasher(),
new CRC32TableHasher(),
new TrigHasher()
};
for (Hasher hasher : hashers)
{
test(hasher);
}
}
}
The simplest hash for int value is the int value.
See Java Integer class
public int hashCode()
public static int hashCode(int value)
Returns:
a hash code value for this object, equal to the primitive int value represented by this Integer object.

Java hashCode for a Point class

I have a simple custom Point class as follows and I would like to know if my hashCode implemention could be improved or if this is the best it's going to get.
public class Point
{
private final int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
#Override
public boolean equals(Object other)
{
if (this == other)
return true;
if (!(other instanceof Point))
return false;
Point otherPoint = (Point) other;
return otherPoint.x == x && otherPoint.y == y;
}
#Override
public int hashCode()
{
return (Integer.toString(x) + "," + Integer.toString(y)).hashCode();
}
}
Please do not use Strings. There's a lot of theory behind this and several implementations (division method, multiplication one, etc...). If you have about a hour you can watch this MIT-Class
This being said, here is what Netbeans 7.1 suggests:
#Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + this.x;
hash = 71 * hash + this.y;
return hash;
}
October 2015 Edit
I started using IntelliJ a while back, I live happier now. This is what its automatic hashCode generation produces. It's a little less verbose. Note the use of prime numbers as well.
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
The manual multiplication of values of all significant member fields as suggested by Gevorg is probably the most efficient and has a good value distribution. However, if you favour readability, there are nice alternatives available either in Java 7...
import java.util.Objects;
...
#Override
public int hashCode() {
return Objects.hash(x, y);
}
... or in the Guava library:
import com.google.common.base.Objects;
....
#Override
public int hashCode() {
return Objects.hashCode(x, y);
}
Both of these varags methods simply delegate to Arrays.hashCode(Object[] a), so there is a slight impact on performance because of the autoboxing of ints and creating an array of object references, but it should be far less significant than using reflection.
And the readability is just great, since you simply see, which fields are used for the hashcode computation and all the multiply and add syntax is just hidden under the hood of Arrays.hashCode(Object[] a):
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
I would recommend using a simpler and more performant method without strings, perhaps Josh Bloch's method from this answer, in your case just:
return 37 * x + y;
EDIT: nybbler is correct. What is actually recommended is:
int result = 373; // Constant can vary, but should be prime
result = 37 * result + x;
result = 37 * result + y;
A really nice way to hash a 2D point into a single integer is to use a number spiral!
http://ulamspiral.com/images/IntegerSpiral.gif
#Override
public int hashCode() {
int ax = Math.abs(x);
int ay = Math.abs(y);
if (ax>ay && x>0) return 4*x*x-3*x+y+1;
if (ax>ay && x<=0) return 4*x*x-x-y+1;
if (ax<=ay && y>0) return 4*y*y-y-x+1;
return 4*y*y-3*y+x+1;
}
While this method requires a few more calculations, there will be no unpredictable collisions. It also has the nice property that points closer to the origin in general will have smaller hash value. (Still can overflow with x or y > sqrt(MAX_VALUE) however)
From the JDK's Point class (inherited from Point2d):
public int hashCode() {
long bits = java.lang.Double.doubleToLongBits(getX());
bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
return (((int) bits) ^ ((int) (bits >> 32)));
}
That looks slightly better than your implementation.
You can have a look into existing Point type classes implementations:
/**
343 * Returns the hashcode for this <code>Point2D</code>.
344 * #return a hash code for this <code>Point2D</code>.
345 */
346 public int hashCode() {
347 long bits = java.lang.Double.doubleToLongBits(getX());
348 bits ^= java.lang.Double.doubleToLongBits(getY()) * 31;
349 return (((int) bits) ^ ((int) (bits >> 32)));
350 }
from: http://kickjava.com/src/java/awt/geom/Point2D.java.htm#ixzz1lMCZCCZw
Simple guide for hashCode implementation can be found here
I used to write my own hash and equals functions then I found this : )
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
#Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
of course keep in mind the following:
Because reflection involves types that are dynamically resolved,
certain Java virtual machine optimizations can not be performed.
Consequently, reflective operations have slower performance than their
non-reflective counterparts, and should be avoided in sections of code
which are called frequently in performance-sensitive applications. SRC
By default, Eclipse will use a hashCode() function for your Point class similar to:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + x;
result = prime * result + y;
return result;
}
At the very least, incorporating a prime number into your hashCode algorithm will help with it's "uniqueness".

Categories

Resources