在Go中丢失了将float32数转换为float64的精度。例如,将359.9转换为float64会生成359.8999938964844。如果float32可以精确存储,为什么float64会丢失精度?
示例代码:
package main
import (
"fmt"
)
func main() {
var a float32 = 359.9
fmt.Println(a)
fmt.Println(float64(a))
}
上试试
答案 0 :(得分:9)
从float
(即float32)转换为double
(float64)时,从不会失去精度。前必须是后者的子集。
这与输出格式化程序的默认精度有关。
最近的IEEE754 float
到359.9
359.899993896484375
最近的IEEE754 double
到359.9
359.8999999999999772626324556767940521240234375
最近的IEEE754 double
至359.899993896484375
359.899993896484375
(即是相同的;由于我已经提到的子集规则)。
因此,您可以看到float64(a)
与float64(359.899993896484375)
相同,即359.899993896484375
。这解释了输出,虽然您的格式化程序正在舍入最后的2位数。
答案 1 :(得分:5)
这有助于我理解@ FaceyMcFaceFace的回答:
var a float32 = math.Pi
fmt.Println(a)
fmt.Println(float64(a))
fmt.Println(float64(math.Pi))
3.1415927
3.1415927410125732
3.141592653589793
答案 2 :(得分:1)
我遇到了同样的问题,我对接受的答案不满意,因为它并没有真正解释 Go 中的浮点转换行为。这是一个让我感到困惑的示例代码,它表明在 Golang 中将 float32 转换为 float64 时发生了一些奇怪的事情。如果有人更详细地解释这一点,我将不胜感激。
package main
import (
"fmt"
)
func main() {
var f32 float32 = 0.2
var f64 float64 = 0.2
if float64(f32) == f64 { // this is false
fmt.Println("Check succeeded")
} else {
fmt.Println("Check failed")
}
if float32(f64) == f32 { // this is true
fmt.Println("Check succeeded")
} else {
fmt.Println("Check failed")
}
if float64(float32(f64)) == f64 { // this is false
fmt.Println("Check succeeded")
} else {
fmt.Println("Check failed")
}
}
https://play.golang.org/p/k2ctx4Zfehy
如果转换后数字变得不同,这不是精度损失吗?或者它应该被称为其他术语,但这绝对不是预期的行为,可能会导致许多令人讨厌的错误和混乱。我在对我的应用程序进行单元测试时遇到了这个问题,其中第三方库正在进行从 float32 到 float64 的转换。我无法正确解释这一点,但我在这里学到的是,转换浮点数时必须非常小心,除非确实需要,否则不应这样做 =)