Skip to content

Commit

Permalink
fix geohash's comparison according to base32 encoded comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
0mok committed Apr 22, 2015
1 parent cdf0b9b commit 12550a3
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/main/java/ch/hsr/geohash/GeoHash.java
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,11 @@ private long maskLastNBits(long value, long n) {

@Override
public int compareTo(GeoHash o) {
return new Long(bits).compareTo(o.bits);
int bitsCmp = Long.compare(bits ^ FIRST_BIT_FLAGGED, o.bits ^ FIRST_BIT_FLAGGED);
if (bitsCmp != 0){
return bitsCmp;
} else {
return Integer.compare(significantBits, o.significantBits);
}
}
}
24 changes: 24 additions & 0 deletions src/test/java/ch/hsr/geohash/GeoHashTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,28 @@ public void testStepsBetween() {
assertEquals(steps, lonLess + latLess + latMore + lonMore + inBbox - latLessLonMore - latMoreLonLess - 1);

}

@Test
public void testCompareTo() {
GeoHash prevHash = null;
for (int i = 0; i < 1000000; i++) {
double latitude = rand.nextDouble() * 180 - 90;
double longitude = rand.nextDouble() * 360 - 180;
int numberOfBits = rand.nextInt(6) * 10 + 10;
GeoHash hash = GeoHash.withBitPrecision(latitude, longitude, numberOfBits);
if (i >= 1) {
String prevHashBase32 = prevHash.toBase32();
String hashBase32 = hash.toBase32();
String errorMessage = String.format("prev: %s, cur: %s", prevHashBase32, hashBase32);
if (prevHashBase32.compareTo(hashBase32) < 0) {
assertTrue(errorMessage, prevHash.compareTo(hash) < 0);
} else if (prevHashBase32.compareTo(hashBase32) > 0) {
assertTrue(errorMessage, prevHash.compareTo(hash) > 0);
} else {
assertTrue(errorMessage, prevHash.compareTo(hash) == 0);
}
}
prevHash = hash;
}
}
}

2 comments on commit 12550a3

@kungfoo
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look at this right away.

@rutujmirzapure
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Fixed geohash comparison to align with base32 encoding standards. The previous method did not correctly account for special cases where the sign of the geohash bits affects comparison. The new approach uses XOR with FIRST_BIT_FLAGGED to handle this properly, ensuring geohashes are compared correctly. Added test coverage to validate this behavior."

here is code that while help u.
@OverRide
public int compareTo(GeoHash o) {
// XOR with FIRST_BIT_FLAGGED to handle sign differences in geohash bits.
int bitsCmp = Long.compare(bits ^ FIRST_BIT_FLAGGED, o.bits ^ FIRST_BIT_FLAGGED);
if (bitsCmp != 0) {
// If bits comparison is non-zero, return the result.
return bitsCmp;
} else {
// If bits are equal, compare by the number of significant bits.
return Integer.compare(significantBits, o.significantBits);
}
}``

Please sign in to comment.