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. Spring注解@Configuration是如何被处理的?

    从SpringApplication开始 一般情况下启动SpringBoot都是新建一个类包含main方法,然后使用SpringApplication.run来启动程序: @SpringBootApp ...

  2. spark集群搭建(三台虚拟机)——系统环境搭建(1)

    !!!该系列使用三台虚拟机搭建一个完整的spark集群,集群环境如下: virtualBox5.2.Ubuntu14.04.securecrt7.3.6_x64英文版(连接虚拟机) jdk1.7.0. ...

  3. nyoj 75-日期计算 (闰年与平年的判断)

    75-日期计算 内存限制:64MB 时间限制:3000ms 特判: No 通过数:19 提交数:31 难度:1 题目描述: 如题,输入一个日期,格式如:2010 10 24 ,判断这一天是这一年中的第 ...

  4. nyoj 266-字符串逆序输出 (isdigit(), geline(cin, my_string))

    266-字符串逆序输出 内存限制:64MB 时间限制:3000ms 特判: No 通过数:15 提交数:18 难度:0 题目描述: 给定一行字符,逆序输出此行(空格.数字不输出) 输入描述: 第一行是 ...

  5. ArcGIS API For Javascript :读取 CSV 文件的方法

    我们临时会遇到一些测试数据,通常从数据库中以 CSV 格式导出.最简单实用的方法就是使用 ajax 去读取文件,记得引入 jQuery . 例如,在<ArcGIS JS API :新增一个热力图 ...

  6. 领扣(LeetCode)设计哈希映射 个人题解

    不使用任何内建的哈希表库设计一个哈希映射 具体地说,你的设计应该包含以下的功能 put(key, value):向哈希映射中插入(键,值)的数值对.如果键对应的值已经存在,更新这个值. get(key ...

  7. Python 之路 Day01 笔记-什么是变量,常量等

    变量 变量 是 为了存储 程序运算过程中的一些中间 结果,为了方便日后调用 变量的命名规则 1. 要具有描述性 2. 变量名只能'_','数字','字母'组成,不可以是空格或特殊字符(#?<., ...

  8. JSAPI 基于arcgis_js_api3.3的部署

    JSAPI,即ArcGIS API For JavaScript,是arcgis基于JavaScript环境下的开发包.包含Dojo框架. ||Dojo结构如下:=================== ...

  9. Java基础知识总结之1.8新特性lambda表达式

    函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的java.lang.Runnab ...

  10. 【2018寒假集训 Day2】【动态规划】维修栅栏

    维修栅栏 问题描述: 小z最近当上了农场主!不过,还没有来得及庆祝,一件棘手的问题就摆在了小z的面前.农场的栅栏,由于年久失修,出现了多处破损.栅栏是由n块木板组成的,每块木板可能已经损坏也可能没有损 ...