【问题标题】:golang losing precision while converting float32 to float64?golang在将float32转换为float64时失去精度?
【发布时间】:2021-07-12 16:02:44
【问题描述】:

在 Golang 中,似乎当一个 float64 var 先转换为 float32 再转换为 float64 时,它的值会发生变化。

a := -8888.95
fmt.Println(a)                    // -8888.95
fmt.Println(float32(a))           // -8888.95
fmt.Println(float64(float32(a)))  // -8888.9501953125

我怎样才能让它保持不变

【问题讨论】:

标签: go floating-point double


【解决方案1】:

您描述问题的方式可能具有误导性。

“将float32转换为float64时”不丢失精度;而是从 float64 转换为 float32 时丢失。

那么在从 float64 转换为 float32 时如何避免丢失精度?你不能。这个任务是不可能的,很容易看出原因:

  • float64 的位数是 float32 的两倍
  • 由于pigeonhole principle,多个不同的float64值将映射到相同的float32值
  • 因此转换是不可逆的。
package main

import (
    "fmt"
)

func main() {
    a := -8888.95
    fmt.Printf("%.20f\n", a)
    fmt.Printf("%.20f\n", float32(a))
    fmt.Printf("%.20f\n", float64(float32(a)))
}

调整您的程序以显示每个值的更精确输出,您将准确地看到精度丢失的位置:

-8888.95000000000072759576
-8888.95019531250000000000
-8888.95019531250000000000

即float32转换后(如预期)。

同样值得注意的是,float64 和 float32 都不能准确地代表您的值 -8888.95。如果将此数字转换为分数,您将得到-177779/20。注意分母 20。20 的素数分解是 2 * 2 * 5。

如果您将此过程应用于一个数字并且分母的素数分解包含任何不是 2 的因子,那么您可以放心,这个数字绝对不能以二进制浮点形式精确表示。您可能会发现任何数字通过此测试的概率都非常低。

【讨论】:

    猜你喜欢
    • 2017-01-31
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    • 2016-06-14
    • 2019-05-21
    • 2015-12-07
    • 2022-12-31
    • 2018-01-30
    相关资源
    最近更新 更多