首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure中的Haversine公式

Clojure中的Haversine公式
EN

Code Review用户
提问于 2017-03-02 15:13:02
回答 1查看 337关注 0票数 5

我实现了Haversine公式来计算两个坐标(纬度、经度)之间的距离。

我在想,对于Clojure程序员来说,这看上去是否很自然。还有什么可以改进的?

代码语言:javascript
复制
(ns br.com.reactive-poc.calc)

(def raio 6372.795477598)

(defn calculate-distance
"Calcula distância entre duas coordenadas geográficas"
([source to]
  {:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}
  (let [delta-latitude (Math/toRadians (- (:source/ltd source) (:to/ltd to)))
        delta-longitude (Math/toRadians (- (:source/lgt source) (:to/lgt to)))
        ]
    (* (* raio (* 2 (Math/atan2 (Math/sqrt (+ (Math/pow (Math/sin (/ delta-latitude 2)) 2) 
                                              (* (Math/cos (Math/toRadians (:source/ltd source))) (Math/cos (Math/toRadians (:to/ltd to))) (Math/sin (/ delta-longitude 2)) (Math/sin (/ delta-longitude 2))))) 
                                (Math/sqrt (- 1 (+ (Math/pow (Math/sin (/ delta-latitude 2)) 2) 
                                                   (* (Math/cos (Math/toRadians (:source/ltd source))) (Math/cos (Math/toRadians (:to/ltd to)) ) (Math/sin (/ delta-longitude 2)) (Math/sin (/ delta-longitude 2))))))))) 1000)
    )
  )
)
EN

回答 1

Code Review用户

发布于 2017-05-13 13:16:22

预条件

  • 不起作用
  • 修正后,与函数所需的数据形状不一致。

让我们减少这个函数,这样它就可以分解它的参数:

代码语言:javascript
复制
(defn calculate-distance
  "Calcula distância entre duas coordenadas geográficas"
  [source to]
  {:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}
  (let [delta-latitude (Math/toRadians (- (:source/ltd source) (:to/ltd to)))
        delta-longitude (Math/toRadians (- (:source/lgt source) (:to/lgt to)))]
    [delta-latitude delta-longitude]))

(我已经不使用包含单个数据的无害但多余的括号了)。

前提是

代码语言:javascript
复制
{:pre [every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to]]}

这反过来评估,

  • every?
  • (every-pred map? #(contains? % :lgt) #(contains? % :ltd))
  • [source to]

..。所有这些在逻辑上都是正确的--两个函数和一个向量。

您需要将整个表达式包装在( ... )中,以使其评估:

代码语言:javascript
复制
{:pre [(every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to])]}

在我们这样做之前,让我们看一下函数所需的数据形状。例如,

代码语言:javascript
复制
(calculate-distance {:source/ltd 0, :source/lgt 0}
                    {:to/ltd 0, :to/lgt 0})
=> [0.0 0.0]

let中的表达式使用限定关键字::source/ltd .。

这很糟糕。我们希望用相同的形状指定两个点--因为它们实际上是对称的:从这里到那里的距离和从这里到这里的距离是一样的。

让我们来看看(校正的)前提条件所需的形状:

代码语言:javascript
复制
(defn calculate-distance
  "Calcula distância entre duas coordenadas geográficas"
  [source to]
  {:pre [(every? (every-pred map? #(contains? % :lgt) #(contains? % :ltd)) [source to])]}
  (let [delta-latitude (Math/toRadians (- (:ltd source) (:ltd to)))
        delta-longitude (Math/toRadians (- (:lgt source) (:lgt to)))]
    [delta-latitude delta-longitude]))

现在

代码语言:javascript
复制
(calculate-distance {:source/ltd 0, :source/lgt 0}
                    {:to/ltd 0, :to/lgt 0})
AssertionError ...

代码语言:javascript
复制
(calculate-distance {:ltd 0, :lgt 0}
                    {:ltd 0, :lgt 0})
=> [0.0 0.0]

到现在为止还好。

让我们举几个简单的例子:

代码语言:javascript
复制
(calculate-distance {:ltd 0, :lgt 0}
                    {:ltd 0, :lgt 0})
=> 0.0

好的。

代码语言:javascript
复制
(calculate-distance {:ltd 0, :lgt 0}
                    {:ltd 0, :lgt 90})
=> 1.0010363727626067E7

从北极到赤道沿格林威治子午线的距离约为一千万米或一万公里--没错。

至于计算,我对其他的答案没有什么可补充的。尽管我希望在JVM环境中像您这样做并直接调用Math函数。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/156722

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档