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算法逆地址编码原理初探的更多相关文章

  1. Python源代码剖析笔记3-Python运行原理初探

    Python源代码剖析笔记3-Python执行原理初探 本文简书地址:http://www.jianshu.com/p/03af86845c95 之前写了几篇源代码剖析笔记,然而慢慢觉得没有从一个宏观 ...

  2. SHA-256算法和区块链原理初探

    组内技术分享的内容,目前网上相关资料很多,但读起来都不太合自己的习惯,于是自己整理并编写一篇简洁并便于(自己)理解和分享的文章. 因为之前对密码学没有专门研究,自己的体会或理解会特别标注为" ...

  3. geohash算法原理及实现方式

    1.geohash特点 2.geohash原理 3.geohash的php .python.java.C#实现代码 4.观点讨论 w微博:http://weibo.com/dxl0321 geohas ...

  4. geohash 算法原理及实现方式

    转自:http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html geohash 算法原理及实现方式 1.geohash 特点 ...

  5. Python下探究随机数的产生原理和算法

    资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...

  6. 【python测试开发栈】带你彻底搞明白python3编码原理

    在之前的文章中,我们介绍过编码格式的发展史:[文章传送门-todo].今天我们通过几个例子,来彻底搞清楚python3中的编码格式原理,这样你之后写python脚本时碰到编码问题,才能有章可循. 我们 ...

  7. Python动态网页爬虫-----动态网页真实地址破解原理

    参考链接:Python动态网页爬虫-----动态网页真实地址破解原理

  8. 转发:吐血总结,彻底明白 python3 编码原理

    吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...

  9. LBS地理位置距离计算方法之geohash算法

    随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等).基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近.这里需要在设置出一个字段, ...

随机推荐

  1. static静态关键字

    转载自大佬:https://www.cnblogs.com/xrq730/p/4820992.html 静态资源和静态方法 首先,静态的资源和方法等会随着类的加载而进入内存被初始化,而非静态的资源和方 ...

  2. 使用Rider中搭建specflow+xunit+selenium对web页面进行自动化功能测试环境

    运行rider,创建测试解决方案,选择xunit,点击create创建 ​   导入包,由于本人使用chrome浏览器(需先下载好对应的浏览器驱动),所以导入了selenium.webdriver.c ...

  3. 易语言 史诗级Json处理 烁_Json模块!!!!

    大家好,我是键盘上的魔手 * “************************”* “** 欢迎使用烁Json模块 **”* “** 作者:键盘上的魔手 **”* “**  微信号:codervip ...

  4. LeetCode18. 四数之和

    LeetCode18. 四数之和 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值 ...

  5. nyoj 45-棋盘覆盖 (高精度, Java)

    棋盘覆盖 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的 ...

  6. 星际争霸2 AI开发(持续更新)

    准备 我的环境是python3.6,sc2包0.11.1 机器学习包下载链接:pysc2 地图下载链接maps pysc2是DeepMind开发的星际争霸Ⅱ学习环境. 它是封装星际争霸Ⅱ机器学习API ...

  7. Ubuntu 16.04 安装Maven3.3.9

    1 下载地址 http://maven.apache.org/download.cgi 2 将下载到的apache-maven-3.3.9-bin.tar.gz文件上传到/temp目录下,然后切换到r ...

  8. 2018.3.7java 学习第二天

    java 学习的第二天,首先我们要学习的是声明变量,在程序中,我们必须先声明变量,然后才可以去使用之,那么变量究竟是什么呢? 在很多课本上,有很多的定义诸如:“变量来源于数学,是计算机语言中能储存计算 ...

  9. python_08

    一.作业 ''' 主页: 图标地址.下载次数.大小.详情页地址 详情页: 游戏名.好评率.评论数.小编点评.下载地址.简介.网友评论.1-5张截图链接地址. https://www.wandoujia ...

  10. 配置k8s集群context-rbac实践

    说明 在openshift环境中,可以通过oc project {project_name}命令来切换project,那么在k8s中式如何切换namespace的呢?(ocp的project即相当于k ...