为什么我在将 float32 转换为 float64 时会丢失精度?
Why am I losing precision while converting float32 to float64?
虽然将 float32 数字转换为 float64 精度在 Go 中丢失。例如,将 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))
}
试试 Playground
当从 float
(即 float32)转换为 double
(float64)时,您 永远不会 失去精度。前者必须是后者的子集
更多的是与输出格式化程序的默认精度有关。
最接近 359.9 的 IEEE754 float
是
359.899993896484375
最接近 359.9 的 IEEE754 double
是
359.8999999999999772626324556767940521240234375
距离 359.899993896484375 最近的 IEEE754 double
是
359.899993896484375
(即相同;由于我已经提到的子集规则)。
所以你可以看到 float64(a)
与 float64(359.899993896484375)
相同,即 359.899993896484375
。这解释了该输出,尽管您的格式化程序正在四舍五入最后的 2 位数字。
这帮助我理解了@FaceyMcFaceFace 的回答:
var a float32 = math.Pi
fmt.Println(a)
fmt.Println(float64(a))
fmt.Println(float64(math.Pi))
3.1415927
3.1415927410125732
3.141592653589793
我遇到了同样的问题,我对接受的答案不满意,因为它并没有真正解释 Go 中的 float 转换行为。这是一个令我困惑的示例代码,它表明在 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 的转换。我无法正确解释这一点,但我在这里学到的是,你必须非常小心地转换浮点数,除非你真的需要,否则你不应该这样做 =)
虽然将 float32 数字转换为 float64 精度在 Go 中丢失。例如,将 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))
}
试试 Playground
当从 float
(即 float32)转换为 double
(float64)时,您 永远不会 失去精度。前者必须是后者的子集
更多的是与输出格式化程序的默认精度有关。
最接近 359.9 的 IEEE754 float
是
359.899993896484375
最接近 359.9 的 IEEE754 double
是
359.8999999999999772626324556767940521240234375
距离 359.899993896484375 最近的 IEEE754 double
是
359.899993896484375
(即相同;由于我已经提到的子集规则)。
所以你可以看到 float64(a)
与 float64(359.899993896484375)
相同,即 359.899993896484375
。这解释了该输出,尽管您的格式化程序正在四舍五入最后的 2 位数字。
这帮助我理解了@FaceyMcFaceFace 的回答:
var a float32 = math.Pi
fmt.Println(a)
fmt.Println(float64(a))
fmt.Println(float64(math.Pi))
3.1415927
3.1415927410125732
3.141592653589793
我遇到了同样的问题,我对接受的答案不满意,因为它并没有真正解释 Go 中的 float 转换行为。这是一个令我困惑的示例代码,它表明在 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 的转换。我无法正确解释这一点,但我在这里学到的是,你必须非常小心地转换浮点数,除非你真的需要,否则你不应该这样做 =)