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 可能有助于确定哪些值适合您的项目。
一些注意事项:
有两个潜在的问题在起作用:
浮点数:
一些可能会阐明浮点问题的读物:
- What Every Programmer Should Know About Floating-Point Arithmetic or Why don’t my numbers add up?
- What Every Computer Scientist Should Know About Floating-Point Arithmetic
如果你阅读了这些,并且理解了浮点数是如何工作的
修行,你可能开悟,明白是怎么回事
以及如何解决它。
测量精度:
在我看来,这是一个更大的问题。您发布的一个号码是 13.519004709972312
,显示为 13.519004709972313
。无论该值是否具有 "changed"(请参阅:1),我尝试计算这些值之间的差异的每个软件计算器都返回 0
,这是指示性的。
手工计算显示值有 0.000000000000001
的差异。也就是说,尾随一个之前有 14 个零,或 1^-15
。
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。
即使我所有的计算都错了一百万或十亿倍,距离仍然很小,在实践中它们无关紧要!
我正在尝试从 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 可能有助于确定哪些值适合您的项目。
一些注意事项:
有两个潜在的问题在起作用:
浮点数:
一些可能会阐明浮点问题的读物:
- What Every Programmer Should Know About Floating-Point Arithmetic or Why don’t my numbers add up?
- What Every Computer Scientist Should Know About Floating-Point Arithmetic
如果你阅读了这些,并且理解了浮点数是如何工作的 修行,你可能开悟,明白是怎么回事 以及如何解决它。
测量精度:
在我看来,这是一个更大的问题。您发布的一个号码是
13.519004709972312
,显示为13.519004709972313
。无论该值是否具有 "changed"(请参阅:1),我尝试计算这些值之间的差异的每个软件计算器都返回0
,这是指示性的。手工计算显示值有
0.000000000000001
的差异。也就是说,尾随一个之前有 14 个零,或1^-15
。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。
即使我所有的计算都错了一百万或十亿倍,距离仍然很小,在实践中它们无关紧要!