geoHash的问题这篇博客(https://www.jianshu.com/p/7332dcb978b2)里已经写得非常完善了, 本文从数学方面来解释一下它的一些缺陷。明白GeoHash原理的话可以直接看最后一段

一、皮亚诺曲线的数学论证

以下内容节选自知乎:

皮亚诺曲线很有名气,它是一个“填满单位正方形的曲线”,不过它也让人迷惑,一个坑是它其实有过好几个定义,而即使是维基百科,上面的介绍也是错的;另一个坑是,它是按照曲线族的极限定义的,而极限与曲线族中的任意一条曲线,性质未必相同。

比如维基说:“1890年,意大利数学家[朱塞佩·皮亚诺]发明能填满一个正方形的曲线,叫做皮亚诺曲线“——嗯,到这里,是对的,让我们把这个称为定义一。

维基继续说:”其构造方法如下:取一个正方形并且把它分出九个相等的小正方形,然后从左下角的正方形开始至右上角的正方形结束,依次把小正方形的中心用线段连接起来;下一步把每个小正方形分成九个相等的正方形,然后上述方式把其中中心连接起来……将这种操作手续无限进行下去,最终得到的极限情况的曲线就被称作皮亚诺曲线。”图如下:

——嗯,这个说法也成立,让我们称这个为定义二。

两个都成立阿,那不挺好吗?问题就在于,这两个定义是不等价的——皮亚诺当年的构造方法,跟定义二里的构造方法,是不一样的。

——————分割线——————

OK,让我们从头说起。严谨一点,称“填满一个正方形的曲线,叫做皮亚诺曲线“这种最广义的说法,为定义零。皮亚诺的方法为定义一,上面整整齐齐的构造方法,为定义二。

皮亚诺当初首要目的,是为了填满正方形,他并不在乎如上图那样整整齐齐。与皮亚诺最类似的构造方法,在张筑生老师《数学分析新讲》第三册里有介绍,是索恩伯格(Isaac Jacob Schoenberg)1938年提出的:

image

image

image

image

整个过程比较罗嗦,其实想法也很简单,就是把小数拆开,一分为二——比如有小数0.12345678,按奇偶拆成0.1357和0.2468——这样单位区间上0到1的一个小数,就拆成了两个,让它们是纵横坐标,就指定了一个点,这样就填满正方形了。用数学语言说,我们要在单位区间[0,1]上定义两个函数phi和psai,使得对任意x属于[0,1],phi(x),psai(x)也属于[0,1]。x从跑到1,(phi(x), psai(x))从(phi(0), psai(0))跑到(phi(1), psai(1)),把点连起来,就是曲线,然后想办法找到合适的phi和psai,让这个曲线能走遍正方形的所有点,就大功告成。

一分为二最简单的就是如上面例子所示按奇数和偶数位拆开——小数0.12345678,拆成小数对(0.1357, 0.2468).

这里让我们再进一步,用二进制表示,那么十进小数0.5,换成二进制就是0.1,写成0.100000....,可以拆成二进制的小数对(0.10000, 0.00000),换成十进制就是(0.5,0)。

到这里似乎还好,问题在于,这样拆,是不连续的,即,phi和psai不连续!不连续的话,x从跑到1,(phi(x), psai(x))跑的点连不起来,就不是曲线。

验证一下:十进小数0.49999999....,换成二进制就是0.0111111.......,可以拆成二进制的小数对(0.011111...., 0.11111.....),这就是(0.1, 1.0),换成十进制就是(0.5,1)。这样,x从0.49999...跳到0.5,(phi(x), psai(x))从(0.5,1)跳到了(0.5,0),步子太大,断了。

怎么办?上面Schoenberg的构造方法就是来解决这个问题的,简而言之,他引入了三进制,多了一个缓冲区间,这样就把两边连起来了。

Schoenberg function,是这个样子的:

image

上面张老师的书里的图19-10是基本函数w,Schoenberg fucntion是w的一个无穷级数,即函数序列的极限。

可以证明,Schoenberg function处处连续,处处不可导。

Schoenberg function是phi,phi(3x)是psai(x),形成的曲线是这样的:

image

可以看到,跟上面维基的定义二里的乖宝宝相比,这样形成的皮亚诺曲线(定义一),是狂野的多了。

但不管好不好看,可以看到,任何一个单位正方形内的点,都能合并成一个单位区间的数,换句话说,这样定义的皮亚诺曲线,确实是一个满射,它填满了整个正方形。

——————分割线——————

好,现在让我们讨论定义二的曲线。这个曲线明显舒服的多,它的简化版本是希尔伯特曲线(Hilbert Curve)

image

这个定义很直观,唯一要说明的是一个坑:这样的曲线,似乎每一个条线段端点,至少有一个坐标是有理数,那这样的曲线能否经过两个坐标都是无理数的点呢?比如(1/pi, 1/pi)。

这就回到了开头说的:曲线族的极限与曲线族中的任意一条曲线,性质未必相同。

例如有这样的曲线族fk(x) =1/k,很显然任意一条曲线都有f_k(x)>0,但这个曲线族的极限很显然是f(x)=0。

可以证明,定义二所述的皮亚诺曲线,作为曲线族的极限,是经过正方形内的每一个点的,它也是满射。

——————分割线——————

关于皮亚诺曲线的维度和面积,”等待飞翔“的回答里已经阐述,不再赘述。

——————分割线——————

geoHash问题

Geohash 一个点附近的地方(但不绝对) hash 字符串总是有公共前缀,并且公共前缀的长度越长,这两个点距离越近。

由于这个特性,Geohash 就常常被用来作为唯一标识符。用在数据库里面可用 Geohash 来表示一个点。Geohash 这个公共前缀的特性就可以用来快速的进行邻近点的搜索。越接近的点通常和目标点的 Geohash 字符串公共前缀越长(但是这不一定,也有特殊情况,下面举例会说明)

Geohash 也有几种编码形式,常见的有2种,base 32 和 base 36。

Decimal

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Base 32

0

1

2

3

4

5

6

7

8

9

b

c

d

e

f

g

Decimal

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

Base 32

h

j

k

m

n

p

q

r

s

t

u

v

w

x

y

z

base 36 的版本对大小写敏感,用了36个字符,“23456789bBCdDFgGhHjJKlLMnNPqQrRtTVWX”。

Decimal

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Base 36

2

3

4

5

6

7

8

9

b

B

C

d

D

F

g

G

h

H

j

Decimal

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

Base 36

J

K

I

L

M

n

N

P

q

Q

r

R

t

T

V

W

X

Geohash 实际应用举例

接下来的举例以 base-32 为例。举个例子。

假设需要查询距离美罗城最近的餐馆,该如何查询?

第一步我们需要把地图网格化,利用 geohash。通过查表,我们选取字符串长度为6的矩形来网格化这张地图。

经过查询,美罗城的经纬度是[31.1932993, 121.43960190000007]。

先处理纬度。地球的纬度区间是[-90,90]。把这个区间分为2部分,即[-90,0),[0,90]。31.1932993位于(0,90]区间,即右区间,标记为1。然后继续把(0,90]区间二分,分为[0,45),[45,90],31.1932993位于[0,45)区间,即左区间,标记为0。一直划分下去。

左区间

中值

右区间

二进制结果

-90

0

90

1

0

45

90

0

0

22.5

45

1

22.5

33.75

45

0

22.5

28.125

33.75

1

28.125

30.9375

33.75

1

30.9375

32.34375

33.75

0

30.9375

31.640625

32.34375

0

30.9375

31.2890625

31.640625

0

30.9375

31.1132812

31.2890625

1

31.1132812

31.2011718

31.2890625

0

31.1132812

31.1572265

31.2011718

1

31.1572265

31.1791992

31.2011718

1

31.1791992

31.1901855

31.2011718

1

31.1901855

31.1956786

31.2011718

0

再处理经度,一样的处理方式。地球经度区间是[-180,180]

左区间

中值

右区间

二进制结果

-180

0

180

1

0

90

180

1

90

135

180

0

90

112.5

135

1

112.5

123.75

135

0

112.5

118.125

123.75

1

118.125

120.9375

123.75

1

120.9375

122.34375

123.75

0

120.9375

121.640625

122.34375

0

120.9375

121.289062

121.640625

1

121.289062

121.464844

121.640625

0

121.289062

121.376953

121.464844

1

121.376953

121.420898

121.464844

1

121.420898

121.442871

121.464844

0

121.420898

121.431885

121.442871

1

纬度产生的二进制是101011000101110,经度产生的二进制是110101100101101,按照“偶数位放经度,奇数位放纬度”的规则,重新组合经度和纬度的二进制串,生成新的:111001100111100000110011110110,最后一步就是把这个最终的字符串转换成字符,对应需要查找 base-32 的表。11100 11001 11100 00011 00111 10110转换成十进制是 28 25 28 3 7 22,查表编码得到最终结果,wtw37q。

我们还可以把这个网格周围8个各自都计算出来。

image.png

从地图上可以看出,这邻近的9个格子,前缀都完全一致。都是wtw37。

如果我们把字符串再增加一位,会有什么样的结果呢?Geohash 增加到7位。

image.png

当Geohash 增加到7位的时候,网格更小了,美罗城的 Geohash 变成了 wtw37qt。

看到这里,读者应该已经清楚了 Geohash 的算法原理了。咱们把6位和7位都组合到一张图上面来看。

可以看到中间大格子的 Geohash 的值是 wtw37q,那么它里面的所有小格子前缀都是 wtw37q。可以想象,当 Geohash 字符串长度为5的时候,Geohash 肯定就为 wtw37 了。

接下来解释之前说的 Geohash 和 Z 阶曲线的关系。回顾最后一步合并经纬度字符串的规则,“偶数位放经度,奇数位放纬度”。读者一定有点好奇,这个规则哪里来的?凭空瞎想的?其实并不是,这个规则就是 Z 阶曲线。看下图:

image.png

几个问题

GeoHash的缺点

我们发现在前面的皮亚诺曲线推倒的过程中, 把小数拆开, 一分为二的过程其实和GeoHash中将经纬度合二为一是个相反过程。 以base-32 为例, 我们假设有一个地理位置二进制为(11111, 111111)和另一个(100000,000000)显然他们离的很远, 我们把它变为GeoHash值, 则一个为11111111111, 一个为100000000000,转换为十进制后为001zz 和 00200: 在数值上这两个点相差很小, 但是实际距离相差很大。 这里对应的数学现象就是前边提到的, 单纯的奇偶交叉排列二进制下是不连续的, 我们可以把精度设的越来越高, 但是终究它的极限是跳跃的。 再看上图我们发现凡是涉及到进位操作的时候都有可能会有跳跃。

所以我们可以看出GeoHash在使用过程中不能简单通过GeoHash值是否近似来判断是否离的很近, 而应一次获取圆心附近的九个方框(通过前缀是否相同判定, 由于进位的情况会改变前缀所以会把这种跳跃点忽略), 拿到所有点位后, 通过求欧氏距离来算定远近。

如何找到附近的区块

我们很容易联想到如果一个点在格林尼治天文台附近, 那么单纯通过前缀他会忽略掉离自己很近的目标。 事实上所有处于二分位置的线附近都会有一样的问题, 即明明离的很近, 但是前缀完全不同。 事实上查找附近区块是有规律的

image.png

通过这个图我们可以看出来, base32会把空间分为32块, 每一个小空间的空间排序也是一样的, 这样通过简单的排序规则, 我们就可以找到附近的8个区块的前缀, 然后一次获取9个区块, 再进行欧氏距离计算。

geohash网格图_geoHash的数学局限相关推荐

  1. geohash网格图_Geohash 网格聚合

    Geohash 网格聚合edit 通过一个查询返回的结果数量对在地图上单独的显示每一个位置点而言可能太多了. geohash_grid 按照你定义的精度计算每一个点的 geohash 值而将附近的位置 ...

  2. geohash网格图_GeoHash grid Aggregation(GeoHash网格聚合)

    GeoHash grid Aggregation(GeoHash网格聚合) GeoHash grid Aggregation 在geo_point字段和组上工作的多bucket聚合将指向网格中表示单元 ...

  3. geohash网格图_聊聊GeoHash

    版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 鲁班门前弄大斧,笔者今天要聊一下geohash. redis/elasticsearch/mong ...

  4. geohash网格图_空间索引 - GeoHash算法及其实现优化

    前言 上篇博客中提到了空间索引的用途和多种数据库对空间索引的支持情况,那么在应用层以下,好学的小伙伴应该会考虑空间索引的实现原理了. 目前空间索引的实现有 R树和其变种GIST树.四叉树.网格索引等. ...

  5. LeetCode 1411. 给 N x 3 网格图涂色的方案数(数学)

    1. 题目 你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同). 给你网格图的行数 n ...

  6. 经典文献阅读之--DOGM(动态占用网格图)

    0. 简介 最近在群里被萌新询问2D激光雷达的工作还能做什么,我当时有点难以回答,cartographer作为2D的集大成者,留给后续工作者改进的地方已经很少了.直到我最近看到了这一篇文章<Dy ...

  7. Leetcode69场双周赛-第四题5931. 用邮票贴满网格图

    5931. 用邮票贴满网格图 题目描述 解题思路 查找标志为0的点,尝试以该点为邮票的左上角,直到尝试为以该点为邮票的右下角.如果能放邮票,并覆盖该为0 的点,则把覆盖的点标志为2.如果不能,直接返回 ...

  8. 【数据结构与算法】之给Nx3网格图涂色的方案数的求解算法

    一.题目要求 你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同). 给你网格图的行数 ...

  9. [ZJOI2016]旅行者(网格图分治最短路)

    problem luogu-P3350 solution 据说,网格图最短路用分治是一个人人皆知的套路.对不起我不是人 类比整体二分的算法流程. 考虑在一个 (xl,yl)−(yl,yr)(xl,yl ...

最新文章

  1. 【BZOJ】3542: DZY Loves March
  2. js网页如何获取手机屏幕宽度
  3. IIS 上传文件大小配置步骤(默认200K)
  4. 为什么很多公司转型Go语言开发?Go语言能做什么
  5. matlab程序svm四等级分类,支持向量机(SVM)多分类matlab程序代码
  6. 大幅减少GPU显存占用:可逆残差网络(The Reversible Residual Network)
  7. TinyMCE下载及使用
  8. 沃特玛采集均衡模块_云原生在京东丨云原生时代下的监控:如何基于云原生进行指标采集?...
  9. php对接监控摄像头源码,摄像头监控录像源代码 (详细的代码,可以直接使用,也可以拿来学习使用)...
  10. 你见过马化腾18年前编写的代码吗?
  11. 阴阳师服务器维护6,《阴阳师》手游6月24日维护更新公告
  12. Mysql大数据优化方案
  13. [实用工具] 简单的数独计算器
  14. HDU 4622 Reincarnation (后缀数组|后缀自动机)
  15. 利用HTML+CSS进行页面布局(div的浮动效果)
  16. Jsp页面使用JavaBeans
  17. 华科博士201万,西安交大本科生100万!华为「天才少年」校招薪资曝光
  18. mac 备份文件 太大 时间机器_Mac 时间机器 Time Machine 备份速度太慢的解决方法
  19. DVWA全关教程手册
  20. Android之更换头像

热门文章

  1. [论文笔记]GMNN图马尔可夫网络原理
  2. 艾司博讯:拼多多开专营店需要多少保证金
  3. PYTHON表白代码:还有半个月就要圣诞啦~初雪要来了么?心软的神还会远吗(不知道怎么开口表白的小可爱还不赶紧把素材备好)
  4. CCF 201903-3 损坏的RAID5(Python100分)
  5. 青年教师大讲堂 计算机,青年教师大讲堂 | 第二期海洋与科学技术学院祝捍皓博士开课啦!...
  6. 手机通讯录(纯java)
  7. NX二次开发-NXOPEN C# Part.GetPreviewImage读取prt文件预览图
  8. 【python】24点游戏算法
  9. 看《史记-伯夷叔齐列传》
  10. 软件质量测试中的健壮性测试是什么?一文和你说