Geohash length to be reversible to LatLong using PostGIS

Decode/encode Geohashes are easy, and there are a "rule of the thumb" for estimat mininal Geohashe length for each LatLong precision. The question is other: precision for revesibility,

1. How many digits of Geohash for a symetric GeoURI with P decimal digits of precision? There are a (statistically) reliable formula for this kind of estimation?

2. There are other tool for PostGIS to calculate with better precision the decode/encode of Gehashes?

Example: Geo URI geo:-15.793889,-47.882778, with 6 decimal places, can be transformed into 6vjynkucf (9 base32 digits) that seems good... But to back into the same LatLong we need (theorically) 12 digits.

SQL example with OpenStreetMap points

CREATE or replace VIEW vw_point_geohash_diffs AS
SELECT *, abs(orig_x-x) diff_x, abs(orig_y-y) diff_y
FROM (
SELECT orig_x, round(st_x(pt),6) x, orig_y, round(st_y(pt),6) y
-- the 6 is "6 decimal digits at LatLong coordinates"
FROM (
SELECT osm_id, st_centroid(ST_GeomFromGeoHash( st_geohash(way,14)
-- here ...9, 10, 11, 12, 13, 14...
)) pt,
round(st_x(way),6) orig_x, round(st_y(way),6) orig_y
FROM planet_osm_point
) t1
) t2;
-- Precision checks:
SELECT n, sum_x, sum_y, round(avg_diffs/2.0,10) as avg_diffs, n_diffs_not0,
round(100.0*n_diffs_not0/n,2)||'%' as perc,
round(avg_diffs_not0/2.0,10) as avg_diffs_not0
FROM (
SELECT count(*) n, sum(diff_x) sum_x, sum(diff_y)  sum_y,
avg(diff_x+diff_y)  avg_diffs,
count(*) FILTER (WHERE diff_x>0 OR diff_y>0) n_diffs_not0,
avg(diff_x+diff_y) FILTER (WHERE diff_x>0 OR diff_y>0) avg_diffs_not0
FROM vw_point_geohash_diffs
) t;

The theory is simple: merging all LatLong Digits in a integer number, 1579388947882778 and converting to base32, 1CSE8IJ6OOQ, results in a 11-digit number, that is the theoretic "mininal length". Converting each coordinate the length is 12: base32(15793889)=F1VN1, 5 digits; and base32(47882778)=1DL8GQ, 6 digits; Imaging the worst case, base32(99999999)=2VBO7V, 6 digits. So 6+6=12.

Make sense, see data, a "S curve" for geohash_len X perc, with transition in len=12

geohash_len|  avg_diffs   | n_diffs_not0 |   perc  | avg_diffs_not0
-----------|--------------|--------------|---------|--------
10         | 0.0000020377 |      1786453 | 97.4%   |   0.0000020912
11         | 0.0000003716 |      1111317 | 60.6%   |   0.0000006130
12         | 0.0000000756 |       267843 | 14.6%   |   0.0000005173
13         | 0.0000000489 |       174916 | 9.5%    |   0.0000005127
14         | 0.0000000493 |       176324 | 9.6%    |   0.0000005128

Running all with n=1833326 points (OSM Brazil).

The main problem for "reversible precision" seems the float arithmetic error at Geohash-14 or more. Same problem when we change round from 6 decimal places of LatLong to 5 places,

gh_len|  avg_diffs   | difs_not0 |  perc | avg_diffs_not0
------|--------------|-----------|-------|---------------
9     | 0.0000107338 | 1733044   | 94.53%| 0.0000113549
10    | 0.0000020370 | 679864    | 37.08%| 0.0000054930
11    | 0.0000003749 | 134963    | 7.36% | 0.0000050926
12    | 0.0000000836 | 30480     | 1.66% | 0.0000050300
13    | 0.0000000563 | 20502     | 1.12% | 0.0000050332
14    | 0.0000000570 | 20792     | 1.13% | 0.0000050293

The transition (S curve) is in len=10 or len=11, as expected. The problems arises after Geohash 13 digits, seems internal (floating point?).

PS: conservation of information in translation or format convertion process have its foundations in the notion of thermodynamically reversible process... The answer a/115501/7505 is not correct for this context of "reversibility".

• Another discussion about reversible Geohash, where is expected "that I could get back my original geohash String when I encode the decoded base32 long". See github.com/davidmoten/geo/issues/9 Nov 27 '18 at 17:05