【问题标题】:Go float64 does not work for latitude and longitudeGo float64 不适用于经纬度
【发布时间】:2015-08-27 08:58:29
【问题描述】:

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

我创建了一个快速的 sn-p,以便您可以执行问题: 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)
    }
}

【问题讨论】:

  • 如果你想要比 float64 更高的精度,你应该使用math/big
  • 我已经用完整的代码进行了编辑。谢谢
  • @JimB,不知道怎么做,你能用你的建议修改游乐场的例子吗?
  • 如前所述,您可以(应该?)只使用 float64 并使用舍入。如果您有理由希望保留确切的字符串,json.Number 可能会有一些用处。
  • 另外你必须问自己的问题是输入是如何生成的?如果在源头使用了双精度数字,那么最后的数字无论如何都不能被信任。您可以使用float64 可靠地表示最多 15 个十进制数字,但您的输入有 17 个。

标签: go numbers precision


【解决方案1】:

一个实用的解决方案:

什么都不做。

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

小数点后八位(数字中有 15)代表大约 1.1 毫米的距离。我怀疑你的测量是否准确到这个程度,而且任何事情都变得非常愚蠢。小数点后 5 位约为 1.1m,属于正常范围,不受浮点错误的影响。

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

一些注意事项:

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

  1. 浮点数

    一些可能揭示浮点问题的阅读:

    如果您阅读了这些内容,并了解了浮点的工作原理 练习,您可能会有所启发,并了解正在发生的事情 以及如何解决它。

  2. 测量精度

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

    手动计算发现值有0.000000000000001 的差异。也就是说,在尾随 1 之前有 14 个零,或 1^-15

    wikipedia page on Latitude 说:

    球面上1纬度的子午线长度为111.2公里

    从这里往后推算,纬度中小数点后 15 位表示的位置差异对应于大约 0.00000011 毫米的距离,即 0.11 纳米。

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

    一个原子比人类最粗的头发小一百万倍。一个原子的直径大约在 0.1 到 0.5 纳米之间

    因此,您的测量结果最多会“偏离”单个原子直径的 1/10。

    即使我所有的计算都偏离了一百万或十亿倍,距离仍然如此之小,以至于在实践中它们并不重要!

【讨论】:

  • 感谢您非常完整的回答,非常感谢!
  • @ThomasModeneis 也许你想接受这个人的回答? :)
猜你喜欢
  • 1970-01-01
  • 2019-07-19
  • 2013-09-09
  • 2019-08-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
  • 1970-01-01
  • 2012-08-05
相关资源
最近更新 更多