咕咚运动apk怎样查询与附近人的距离

= 113.873643;
= 22.573969;
define('EARTH_RADIUS',
= 2 * asin(sin($distance
/ (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));
= rad2deg($dlng);
= $distance/EARTH_RADIUS;
= rad2deg($dlat);
= array('left-top'=&array('lat'=&$lat
+ $dlat,'lng'=&$lng-$dlng),
&&&&&&&&'right-top'=&array('lat'=&$lat
+ $dlat,
'lng'=&$lng
+ $dlng),
&&&&&&&&'left-bottom'=&array('lat'=&$lat
'lng'=&$lng
&&&&&&&&'right-bottom'=&array('lat'=&$lat
'lng'=&$lng
+ $dlng)
&&&&&&&&);
print_r($squares['left-top']['lat']);
* from `A` where lat&&0 and lat&{$squares['right-bottom']['lat']} and lat&{$squares['left-top']['lat']} and lng&{$squares['left-top']['lng']} and lng&{$squares['right-bottom']['lng']} &;
getDistanceBetweenPointsNew($latitude1,
$longitude1,
$latitude2,
$longitude2)
= $longitude1
- $longitude2;
= (sin(deg2rad($latitude1))
* sin(deg2rad($latitude2)))
+ (cos(deg2rad($latitude1))
* cos(deg2rad($latitude2))
* cos(deg2rad($theta)));
= acos($miles);
= rad2deg($miles);
* 60 * 1.1515;
&&$kilometers
* 1.609344;
= $kilometers
compact('miles','feet','yards','kilometers','meters');
= array('lat'
=& 40.770623, 'long'
=& -73.964367);
= array('lat'
=& 40.758224, 'long'
=& -73.917404);
= getDistanceBetweenPointsNew($point1['lat'],
$point1['long'],
$point2['lat'],
$point2['long']);
($distance
=& $value)
'.number_format($value,4).'&br
http://www.jb51.net/article/83974.htm(转)
更多关于PHP相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》、《》、《》、《》、《》、《》及《》
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11726次
排名:千里之外
转载:25篇
(1)(2)(4)(2)(3)(8)(4)(1)(7)怎么快速找到:附近的人 - 推酷
怎么快速找到:附近的人
每周日下午 ,微信 simplemain ,老王又如约跟大家聊技术干货了。
想必大家都用过微信的“附近的人”这个功能,可以看到你周围都有谁,然后加个好友啥的。而我们出去吃饭,经常拿出大众点评,看看附近有哪些好吃的。更有,我们现在经常用 uber 或者滴滴打车,你发出一个路线请求,就有附近的司机来抢单。或者,当你用百词斩背单词的时候,可以找个附近的人 PK 单词量(哈哈哈,看到内置广告了吧 ~ )
我们今天不讨论这个功能在产品上的意义,而是讨论讨论在技术上,他是怎么样来实现的。
好了,正式开始今天的话题吧 ~
关于经纬度
说到附近的人,第一个要谈到的就是经纬度。想必大家在初中(或者是高中)的地理课本里早就学过了。我们把地球分成横竖交错的一些格子,每个点都可以用横竖坐标来表示。横线表示纬度(范围在 [-90 & , +90 & ] ),竖线表示经度(范围在 [-180 & , +180 & ] )。比如老王所在的位置,就可以在地图上用经纬度来表示:
如何获取经纬度
既然每个人所在位置都可以用经纬度来表示,那我们如何获取呢?我们现在智能手机基本都可以通过 GPS 或者基站进行定位,只要 app 调用系统的定位函数,就可以轻易拿到这样的数据(当然,需要用户的确认)。当客户端拿到这样的数据以后,就可以将位置信息上传服务器,由服务器来判定附近有哪些人。
好了,该切入关键点了。当服务器收到很多用户的位置信息以后,怎么来判断你周围有哪些人呢?我们先想一个最简单的实现。当平面上只有两个点(分别代表两个人)的时候,我们怎么计算出他们之间的距离呢?
如果把地球看成一个球体,我们比较容易就用立体几何的知识去计算出他们之间的距离。但是这个过程会比较复杂。如果我们相距的两点不是特别远(相对地球半径而言),我们就可以把他们近似看成平面上的两点,用最简单的欧式距离公式 d(A,B) = sqrt((x1-x2)^2 + (y1-y2)^2) ,便可以得到 A 和 B 之间的距离,对吧。
好了,当我们的用户不是太多的时候,我们就可以采用遍历的方法,依次计算出其他所有的点同我的距离 d1 d2 ... dk ,然后按照距离从小到大排序,得到我们想要的结果,对吧?
看起来一切都很美妙,我们来算算时间复杂度。遍历所有的点,计算距离,是一个 O(n) 复杂度的算法,然后排序做 Top ,基本上是一个 O(n * lgn) 的复杂度。所以,总的看来,是一个 O(n * lgn) 复杂度的算法。当然,在计算和排序的过程中我们可以做优化。当在几千个点的时候,我们的服务器都可以轻松应对,如果我们的点变多了呢?比如,几万、几十万……
第一种方案:分布式计算
还记得以前老王讲分布式的文章(忘了的同学请到老王的微信 simplemain 里寻找哈)嘛?
很显然涉及到大量运算的时候,我们可以将这些运算拆分到多个服务器来进行,这样就可以提高我们并行计算的速度和效率。那当我们有几万、十几万用户的时候,我们就可以将这些用户分布到不同的机器上,让每个机器都计算一部分,然后每个机器给出自己机器的 Top ,最后由某一台或几台汇总,给出最后的结果。
比如,第一台机器计算 uid 从 1-10000 的用户和我的距离,并给出最后的 top100 ;第二台机器计算 uid 从
的用户和我的距离,并给出最后的 top100 ……以此类推。最后由 computer-R 来汇总这些 top100 ,并给出排序结果,输出最后的 top100 。
如果当计算的机器特别多, computer-R 就会成为瓶颈,就需要分裂成多台机器,然后再汇总。
这种方案的优点就是:
1 、算法实现简单:只需要用单机版的点点距离判断 + 排序,就可以搞定;
2 、前面的结果相对比较精确:因为距离都是非常精确的欧式距离,所以 TopK 的结果都是比较精确的
1 、消耗机器严重:随着用户量的增加,机器消耗就直线上升;
2 、后面的结果相对不那么精确:在每台机器做 TopN 以后,实际上就扔掉了其余的数据,最后有可能某台机器上一个很优的结果,没有进入到最后的归并排序。
第二种方案: GeoHash
那我们有没有办法降低对机器的消耗,而且还能在全局做到相对准确的结果排序呢?
其实也是有办法的。具体怎么做呢?跟着老王一起往下看吧。
what to do
如果我们能将地球划分成一个个很小的方形的格子,在同一个格子里的人,是不是就很接近呢?再如果,我们给每个格子编一个代号,那拥有同一个代号的人,是不是就靠的很近呢?这有可能么?那我们就来试试吧 ~
1 、把地球拉成平面:
先假设我们把地球从一个球体拉成一个平面(用几何知识就可以求解相关的对应关系)。
2 、按经度将地球切开
我们以经度 0 &为中轴,将地球切成两半 [-180 & ,0 & ),[0 &, 180 & ] ,并对他们进行二进制编码,左边为 0 ,右边为 1 。
那所有经度坐标在左边的,都得到了 0 这个编码,而其他的则得到 1 这个编码。比如,老王所在位置的经纬度值是 (104..537445) ,老王的经度 104.071398 ∈ [0 &, 180 & ] ,所以编码就是 1 。
好了,接下来我们就进行第二次切割,还是按照老规矩,我们把现有的两个部分也分别切割成左右两个部分,于是得到这样的一个图:
我们得到四个编码: 00 01 10 11 ,每个编码的第一位是第一次切割时候得到的数字, 0 0 0 1 就是第一切割时在左边,编码为 0 ;第二位就是第二次切割,在左边为 00 ,在右边为 01 。同理得到 10 11 。比如,老王所在位置的经纬度值是 (104..537445) ,老王的经度 104.071398 ∈ [90 &, 180 & ] ,所以编码就是 11 。
如此这样重复 N 次,我们就可以将地球按经度切割成很多很多的小块,如果切割的次数足够多,那同一个经度值的人,都会在同一个小块儿里,对吧。那也会得到对应这个小块儿的二进制编码。比如老王的经度 104.071398 经过多次切割得到如下这个表格:
这样,我们就可以得到 104.071398 的编码是:
。随着切分的继续,我们可以得到更长的编码,这样就可以对应更细致的区间。
3 、按纬度将地球切开
用同样的方法,我们按照纬度也把地球切成这样的方式,最终得到对应经纬度的编码:
(104..537445) -& (01011)
老王简单写了一个编码的实现代码:
有了经纬度的切割,地球就被我们划分成了 2 n *2 n 个格子,比如当 n 等于 8 的时候,这个格子数就是 65536 。
4 、统一编码
为了方便记录,我们把经度和维度的二进制格子编码进行合并,按经度、纬度、经度、维度……这样的顺序,一位一位的进行放置:
(104..537445)
-& 1 1 1 0 0 1 0 0 1 1 0 0 1 1 0 1
上面最后的编码,奇数位的红色是经度编码,偶数位的黑色是纬度编码。这样表示起来还是太长了,我们怎么样缩短呢?也很简单,我们可以用 16 进制、 32 进制、 64 进制这样的进制来缩短编码长度。这里业界推荐的是 32 进制,也就是 base32 编码。
这样,每 5 个二进制( 2 5 =32 )组成一个编码字符,于是:
(104..537445)
-& (101011)
-& 1 1 1 0 0 1 0 0 1 1 0 0 1 1 0 1
-& wm6 (3 个完整有效进制数 )
5 、划分的精细度
有了这样的编码,那到底要划分多少次,我们的数据才足够精确呢?我们在维基百科上找到了这样的一张对应表:
当有一个 base32 数字的时候,精细度大概是 2500 公里,当有 8 个数字的时候,精细度大概是 0.019km = 19 米。也就是说, 8 个 base32 的数字 对应 8*5=40 个二进制数,也就是经纬度分别划 20 次,就可以达到 19 米的精细度。这对于我们平时使用已经足够了。
6 、如何查找
有了以上的准备工作,我们就可以给地图上所有的人进行编码了,然后将 (user,code) 这样的 key-value 对放入到数据库的 user_loc_code 表中。当请求某个人附近的人的时候,我只要把这个人的 code 取出来,然后做一个 sql : select * from user_loc_code where code=xxx 就可以得到想要的答案了(不过记得要在 code 上建索引哦 ^_^ )。这个算法的时间复杂度就完全取决于数据库的索引结构(如果是 Hash 索引,则近似 O(1) 算法;如果是 B-Tree 索引,则近似 O(lgn) 算法)。是不是很简单也很高效呢?
稍等!事情还没完呢。如果这个小方形里没有其他人怎么办?产品经理说:我们还是需要给用户返回最近的人!
那其实也很简单,我们只要把编码长度从 1 到 8 的编码都记录下来,我们就拥有了 2500km-0.019km 范围差的所有值,那我们写 sql 的时候,最多写 8 个,就一定能找到我们想要的(一般产品经理会说:我们只要 20 公里范围内的用户,那 sql 最多最多就只需要写 5 个,对吧)。具体的表就可以这样建:
(user, code1, code2, ..., code8) ,记得给每个 code 加上索引哦 ~
7 、话外音
上述的算法,实际上是一个近似算法,我们认为在同一方形格子里的,就是距离最近的,可是实际上呢?
比如, A 和 C 在同一格子里, A 和 B 在不同格子里,但是明显 A 和 B 的距离更近,但是却被硬生生的分开了…… 那这种问题我们如何来解决呢?其实也是有办法的。
如果产品要求不高,我们就不需要解决。如果产品确实要求精度比较高,我们可以取求解的格子的周围其他八个格子的点,然后一起来算距离排序。这样,我们就能求解到最精确的值。
==== 总结的分割线 ====
好了,以上的内容都看懂了嘛?老王其实就喜欢扯扯跟实际工作和生活有关系的一些算法和架构,如果对老王讲的内容感兴趣,就继续在周日下午关注老王的微信 (
simplemain
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致咕咚运动,分享
我的图书馆
咕咚运动,分享
预计阅读时间:5分钟
点击右上角的??,即可收藏文章,随时随地阅读
几乎每一个渴望征服马拉松的人,都希望能在短时间的训练里事半功倍,尽快完成半马、全马的挑战过程。在备战马拉松时,每天都极尽可能把跑步时长、跑步里程最大化,殊不知,并非跑的越久越好。关于马拉松,几乎所有的训练计划都会告诉你四个字:循序渐进,但大多数人都是在受伤之后才能真正理解“循序渐进”的意义。今天,我们就来分享一下马拉松的备赛计划。
起步到10公里 起步都是艰难的,当一个好久没有运动的你鼓足勇气开始跑步,没跑多远就累的上气不接下气时,你可能会觉得自己根本不适合跑步,你更不能想象甚至很多人觉得跑步是一件很享受的事,至于马拉松简直是天方夜谭的事。其实,很多后来跑完马拉松的跑者第一次跑步的时候都和你我一样,天赋禀异的跑者只是少数。给自己多一点时间,你只需要慢一些,再慢一些,如果还是觉得累,可以跑走结合,尽可能让每次的运动时间达到30分钟以上。
有这样一句话叫做:“如果能做到60分钟的边跑边聊,就具备了跑全马的力量。”对于初跑者来说,时间比距离重要,距离比速度重要。坚持慢跑1-2个月时间,大多数人都可以轻松跑5公里左右并开始爱上跑步。 不过,下面几个细节还是要注意一下。   一次完整的跑步应该包括:热身、正常训练、冷却和拉伸几个阶段。你可以从快走开始然后慢跑,逐渐加快训练速度,最后再用一段慢跑和散步冷却,如果你不想要肌肉腿的话跑完一定记得要拉伸。
坚持正确的跑步姿势:上身挺直放松,双肩打开,手臂呈直角前后适度摆动,小步快频,慢慢体会每个部位的动作都是促使身体向前运动,去除任何多余的动作。   增强核心力量训练:核心力量训练可以跑得更轻松,避免受伤,在长距离的运动中保持稳定的跑步姿势。所以每周保持至少2-3次核心力量训练是必要的。
适度休息:休息是跑步训练中非常重要的一部分,初跑者建议每周能休息2天或更多,可以跑2-3天休息一天,也可以跑1休1,根据自己的身体状况和体能而定,感觉到疲惫时就多安排一些跑休。做到以上这些,再循序渐进的跑2-3个月,你就有能力去试试挑战一下10公里。记住坚持慢跑,别着急上速度,容易受伤。
10公里是进入长跑的一个重要里程碑,在10公里左右的单次跑量上慢跑越长时间,累积越多的跑量,你的身体会准备的更充分,伤病的可能性会更小,跨越后面两个阶段会更轻松。建议第一阶段至少坚持半年以上,跑量至少800公里以上后,再进入到下一阶段。 进阶半程马拉松 当你决定进入第二阶段时,请再次确认你从跑步习惯和累积跑量方面,是否已经做好准备,因为距离的增加意味着伤病的概率增加。重要的话来回说,还是不要着急,要循序渐进。
从这一阶段开始,要增加一项长距离慢跑(LSD)。可以每周跑3-4次,平日跑6-10公里,周末一次LSD,并且每周或每2周定期加量。从10公里开始,10、11、12、13.....到21公里一路慢慢加上来。有的跑者很困惑,跑了很多次10公里却很难再增加距离,那是因为你跑的太快了,跑完会累的筋疲力尽,所以一直难以突破,其实只要把速度降一降就很容易拉长距离了。不用太着急练速度,十伤九快,伤病和速度是成正比关系的,而且速度练习同时会破坏有氧基础。
很多时候,我们只看到了高手的速度快,却不知道他们在高速下仍然保持很低的心率,建议初跑者能够在低心率的前提下,循序渐进的提高速度,增加距离。 在力量方面,这个阶段也要更加系统化一些,跑休的日子更要加强力量训练。靠墙静蹲(练习大腿前侧力量保护膝盖)、仰卧起坐(腰腹力量保持跑步稳定性)是最简单最有效的力量练习。
“轻松”跑完马拉松
这里的轻松是相对的,是指在不在意成绩的前提下,有能力全程不走路,不抽筋跑着完赛。
在进入第三阶段时,请确认你能够较为轻松跑完半程,并且至少提前三个月开始备战全程。如果距离你想参加的马拉松准备时间太紧张,建议可以先参加半马。
这一阶段的训练以跑量的积累和长距离跑的训练为主,建议每周跑5次休2次,平日8-15公里,周末一次20-30的长距离跑,隔周适度减量,确保参赛前至少有1次30+的训练。参赛前三到四个月建议月跑量能够达到180公里以上。 做到了以上这些,只要参赛时能在前半程控制好速度,尽量可能慢一些就可以轻松完赛。 把大象装冰箱可能只需要三步,但从零到跑马却没有那么简单。你可以把跑马当成一个目标,但是不要当成一个负担,不然跑步的意义就变了。
点击下面的图片,加入#我的百万计划 做一个在时光中盛开的读行者
TA的最新馆藏[转]&[转]&[转]&

我要回帖

更多关于 咕咚运动软件最新 的文章

 

随机推荐