python geohash算法逆地址编码原理初探
1、geohash有什么用途呢?
这几天刚好有个测试任务是关于设备信息位置处理的,里面提及到geohash;抱着测试的警觉性,打算研读一下这个geohash到底是什么?Geohash 是一种地理编码系统,地球上的任何一个物体可以通过经纬度来定位其在地球位置,而作为程序猿通过经纬度两个信息很难(或者说很麻烦)在数据层面上进行检索和比对,这个时候geohash编码系统出现了,更可以说geohash是一种算法可以把经纬度坐标转换为短字符串。当所有的位置信息都可以通过一个字符串代替时,大大提高了地址检索和比对的效率,通过一个字符串可以知道你的位置信息,广泛应用于定位服务和餐饮服务。同时通过字符串比对可以知道所处位置附近的地址信息。
2、python-geohash如何安装
python3安装python-geohash时一直报错无法安装,但是可以安装geohash,安装完geohash时引用模块会ImportError: No module named ‘geohash’报错,解决方法:
找到site-packages将里面的Geohash文件夹改为geohash,同时在文件夹内部的__init__文件内容改为
from .geohash import decode_exactly, decode, encode
3、geohash源码文件
这里先贴出整个geohash精简源码,预览一下
from math import log10
__base32 = '0123456789bcdefghjkmnpqrstuvwxyz'
__decodemap = { }
for i in range(len(__base32)):
__decodemap[__base32[i]] = i
del i def decode_exactly(geohash):
lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
lat_err, lon_err = 90.0, 180.0
is_even = True
for c in geohash:
cd = __decodemap[c]
for mask in [16, 8, 4, 2, 1]:
if is_even:
lon_err /= 2
if cd & mask:
lon_interval = ((lon_interval[0]+lon_interval[1])/2, lon_interval[1])
else:
lon_interval = (lon_interval[0], (lon_interval[0]+lon_interval[1])/2)
else:
lat_err /= 2
if cd & mask:
lat_interval = ((lat_interval[0]+lat_interval[1])/2, lat_interval[1])
else:
lat_interval = (lat_interval[0], (lat_interval[0]+lat_interval[1])/2)
is_even = not is_even
lat = (lat_interval[0] + lat_interval[1]) / 2
lon = (lon_interval[0] + lon_interval[1]) / 2
return lat, lon, lat_err, lon_err def decode(geohash):
lat, lon, lat_err, lon_err = decode_exactly(geohash)
lats = "%.*f" % (max(1, int(round(-log10(lat_err)))) - 1, lat)
lons = "%.*f" % (max(1, int(round(-log10(lon_err)))) - 1, lon)
if '.' in lats: lats = lats.rstrip('')
if '.' in lons: lons = lons.rstrip('')
return lats, lons def encode(latitude, longitude, precision=12):
lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
geohash = []
bits = [ 16, 8, 4, 2, 1 ]
bit = 0
ch = 0
even = True
while len(geohash) < precision:
if even:
mid = (lon_interval[0] + lon_interval[1]) / 2
if longitude > mid:
ch |= bits[bit]
lon_interval = (mid, lon_interval[1])
else:
lon_interval = (lon_interval[0], mid)
else:
mid = (lat_interval[0] + lat_interval[1]) / 2
if latitude > mid:
ch |= bits[bit]
lat_interval = (mid, lat_interval[1])
else:
lat_interval = (lat_interval[0], mid)
even = not even
if bit < 4:
bit += 1
else:
geohash += __base32[ch]
bit = 0
ch = 0
return ''.join(geohash)
整个算法通过代码的形式就只有不到100行,里面涵盖了正逆地址编码,这里主要看一下逆地址编码算法是如何实现字符串转换为经纬度的。
__base32 = '0123456789bcdefghjkmnpqrstuvwxyz'
__decodemap = { }
for i in range(len(__base32)):
__decodemap[__base32[i]] = i
del i
这段代码的主要作用就是将字符串赋予一个序号如这样,在最后将残余的i删除掉,这一步可以看出作者写代码的规范还是很好的,值得学习!
def decode_exactly(geohash):
lat_interval, lon_interval = (-90.0, 90.0), (-180.0, 180.0)
lat_err, lon_err = 90.0, 180.0
is_even = True
for c in geohash:
cd = __decodemap[c]
for mask in [16, 8, 4, 2, 1]:
if is_even:
lon_err /= 2
if cd & mask:
lon_interval = ((lon_interval[0]+lon_interval[1])/2, lon_interval[1])
else:
lon_interval = (lon_interval[0], (lon_interval[0]+lon_interval[1])/2)
else:
lat_err /= 2
if cd & mask:
lat_interval = ((lat_interval[0]+lat_interval[1])/2, lat_interval[1])
else:
lat_interval = (lat_interval[0], (lat_interval[0]+lat_interval[1])/2)
is_even = not is_even
lat = (lat_interval[0] + lat_interval[1]) / 2
lon = (lon_interval[0] + lon_interval[1]) / 2
return lat, lon, lat_err, lon_err
decode_exactly主要是将geohash解码为它的确切值,包括错误结果的边距。返回四个浮点值:纬度、经度、纬度的正负误差(为正)、经度的正负误差(为正)。
1、先遍历geohash字符串得到每一个字符对应的十进制序号。如k:18 10010
2、判断语句if is_even+mask使整个函数体默认开始是取经度信息(所以在地址编码时偶数位放经度序列奇数为放维度序列合并为二进制字符然后base32编码得到geohash,这里的偶数位是从0开始;扩展如 北京(39.928167 ,116.389550) 编码后(10111 00011 , 11010 01011) , 组码后 :11100 11101 00100 01111 , base32编码后得到最后的geohash值是wx4g)
3、然后通过cd & mask按位与运算符得到当前区间是前半部分还是后半部分(二分法)
4、mask循环体下通过is_even = not is_even实现切换经纬度信息获取机制
5、通过不断的二分规则知道不能在分得到纬度、经度、纬度的正负误差(为正)、经度的正负误差(为正)
def decode(geohash):
lat, lon, lat_err, lon_err = decode_exactly(geohash)
lats = "%.*f" % (max(1, int(round(-log10(lat_err)))) - 1, lat)
lons = "%.*f" % (max(1, int(round(-log10(lon_err)))) - 1, lon)
if '.' in lats: lats = lats.rstrip('')
if '.' in lons: lons = lons.rstrip('')
return lats, lons
这段为逆地址编码主函数,通过表达式%.*f来决定数值的精度有多少为,通过if '.' in lats: lats = lats.rstrip('0')去除尾部的数值0,及2.3000=2.3
至此逆地址源码解析完成,而地址编码其实就是反过来而已。二分法的具体示意图如下
在这段源码中我们需要得到什么呢?
1、一种二分法的使用思路,通过奇数偶数位相错的二进制组合将两个信息合成一个信息然后编码实现可观性字符串
2、通过二分法不断细分保留了所需要的精度值
3、代码精简采用了独特的is_even = not is_even和for mask in [16, 8, 4, 2, 1]来不断的切换奇偶位置
4、geohash应用讨论
1、通过geohash可以详细的知道位置信息
通过源码我们会发现在逆地址解码时存在一定的经纬度数据误差,这就导致了geohash实际表示的是一种很小的范围而不是精准的位置信息,也有助于保护隐私
2、geohash越相近、经纬度越相近
通过逆地址解码源码我们可以知道,解码时时不断的通过二分法对整个平面不断的细分为更小的平面,这就导致会出现平面右下角和平面左下角的值相近的geohash,而经纬度相距较大。
python geohash算法逆地址编码原理初探的更多相关文章
- Python源代码剖析笔记3-Python运行原理初探
Python源代码剖析笔记3-Python执行原理初探 本文简书地址:http://www.jianshu.com/p/03af86845c95 之前写了几篇源代码剖析笔记,然而慢慢觉得没有从一个宏观 ...
- SHA-256算法和区块链原理初探
组内技术分享的内容,目前网上相关资料很多,但读起来都不太合自己的习惯,于是自己整理并编写一篇简洁并便于(自己)理解和分享的文章. 因为之前对密码学没有专门研究,自己的体会或理解会特别标注为" ...
- geohash算法原理及实现方式
1.geohash特点 2.geohash原理 3.geohash的php .python.java.C#实现代码 4.观点讨论 w微博:http://weibo.com/dxl0321 geohas ...
- geohash 算法原理及实现方式
转自:http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html geohash 算法原理及实现方式 1.geohash 特点 ...
- Python下探究随机数的产生原理和算法
资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...
- 【python测试开发栈】带你彻底搞明白python3编码原理
在之前的文章中,我们介绍过编码格式的发展史:[文章传送门-todo].今天我们通过几个例子,来彻底搞清楚python3中的编码格式原理,这样你之后写python脚本时碰到编码问题,才能有章可循. 我们 ...
- Python动态网页爬虫-----动态网页真实地址破解原理
参考链接:Python动态网页爬虫-----动态网页真实地址破解原理
- 转发:吐血总结,彻底明白 python3 编码原理
吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...
- LBS地理位置距离计算方法之geohash算法
随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等).基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近.这里需要在设置出一个字段, ...
随机推荐
- Linux基于webRTC的二次开发(二) 实现远程桌面共享
webRTC中的desktop_capture模块提供了捕获桌面和捕获窗口的相关功能,而实现远程桌面共享功能需要将desktop_capture捕获的画面作为peerconnection的视频源,下面 ...
- visible:hidden和dispaly:none的区别
display:none和visible:hidden都能把网页上某个元素隐藏起来,但两者有区别: display:none ---不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失,通俗来说就 ...
- Hadoop压缩的图文教程
近期由于Hadoop集群机器硬盘资源紧张,有需求让把 Hadoop 集群上的历史数据进行下压缩,开始从网上查找的都是关于各种压缩机制的对比,很少有关于怎么压缩的教程(我没找到..),再此特记录下本次压 ...
- CSS 技巧一则 -- 在 CSS 中使用三角函数绘制曲线图形及展示动画
最近一直在使用 css-doodle 实现一些 CSS 效果. css-doodle 是一个基于 Web-Component 的库.允许我们快速的创建基于 CSS Grid 布局的页面,以实现各种 C ...
- shell配置文件
个人配置主要集中在-/.profile文件中 打开新的交互式shell时,配置文件的执行顺序是/etc/profile /etc/bashrc ~/.profile 最后是~/.bashrc ...
- linux目录数
FHS Filesystem Hierarchy Standard(文件系统层次化标准,[ˈhaɪərɑ:rki] 等级制度)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系 ...
- linux 内核的RCU本质
RCU,Read-Copy Update,是一种同步机制,它的本质就是在同步什么?1. 它只有reader-side lock,并且不产生锁竞争.2. 它同步reader-side 临界区和 recl ...
- (四十五)golang--反射
反射基本介绍: (1)反射可以在运行时动态获取变量的各种信息,比如变量的类型.类别: (2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段.方法): (3)通过反射,可以修改变量的值,可 ...
- linux hwclock
在Linux中,系统时间(软件时间)和硬件时间,并不会自动同步,系统时间和硬件时间以异步的方式运行,互不干扰.硬件时间的运行,是靠Bios电池来维持,而系统时间,是在系统开机的时候,会自动从Bios中 ...
- 2019牛客暑期多校训练营(第九场) E-All men are brothers(并查集+组合数学)
>传送门< 题意:最初有 n个人且互不认识,接下来 m行,每行有 x,y表示x和y交朋友,朋友关系满足自反性和传递性,每次输出当前选取4个人且互不认识的方案数. 思路:比赛的时候知道是用并 ...