Go float64 不适用于经纬度

Go float64 does not work for latitude and longitude

我正在尝试从 json 对象中精确解析纬度和经度,我选择了 float64 来完成这项工作。但是 float64 以某种方式对数字进行四舍五入,我不确定该怎么做才能避免四舍五入。

我创建了一个快速片段,以便您执行该问题: http://play.golang.org/p/9g6Imn-7GK

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type Position struct {
    Lat float64 `json:"lat"`
    Lon float64 `json:"lon"`
}

func main() {
    s := `{"lat":13.519004709972312,"lon": -13.519004709972312}`
    pos := Position{}
    json.Unmarshal([]byte(s), &pos)

    if !reflect.DeepEqual(s, &pos) {
        fmt.Printf("\nExpected %#v\nbut got  %#v", s, pos)
    }
}

一个实用的解决方案:

什么都不做。

数字的差异大约是单个小原子宽度的十分之一,您的测量不可能那么精确。

小数点后第八位(您的数字中有 15)表示大约 1.1 毫米的距离。我怀疑你的测量是否准确到这个程度,再多的东西就变得很傻了。小数点后5位1.1m左右,在理智的范围内,不受浮点数误差的影响。

wikipedia page on Decimal Degrees 可能有助于确定哪些值适合您的项目。

一些注意事项:

有两个潜在的问题在起作用:

  1. 浮点数:

    一些可能会阐明浮点问题的读物:

    如果你阅读了这些,并且理解了浮点数是如何工作的 修行,你可能开悟,明白是怎么回事 以及如何解决它。

  2. 测量精度:

    在我看来,这是一个更大的问题。您发布的一个号码是 13.519004709972312,显示为 13.519004709972313。无论该值是否具有 "changed"(请参阅:1),我尝试计算这些值之间的差异的每个软件计算器都返回 0,这是指示性的。

    手工计算显示值有 0.000000000000001 的差异。也就是说,尾随一个之前有 14 个零,或 1^-15

    wikipedia page on Latitude 说:

    the meridian length of 1 degree of latitude on the sphere is 111.2 km.

    由此推算,纬度小数点后第 15 位表示的位置差异对应的距离约为 0.00000011 毫米,即 0.11 纳米。

    来自 The Physics Factbook 的 Diameter of an Atom 页面:

    An atom is a million times smaller than the thickest human hair. The diameter of an atom ranges from about 0.1 to 0.5 nanometers

    因此,您的测量值最多是单个原子直径的 "off" 1/10。

    即使我所有的计算都错了一百万或十亿倍,距离仍然很小,在实践中它们无关紧要!