【问题标题】:Go: Why does converting from a float64 to a float32 and back cause a change to the value? [duplicate]Go:为什么从 float64 转换为 float32 并返回会导致值发生变化? [复制]
【发布时间】:2021-03-19 22:42:18
【问题描述】:

有没有办法在不改变数据的情况下处理这种转换?

f := float64(-3942.2)
fmt.Println(float64(float32(f))) // = -3942.199951171875

找回-3942.2 的唯一方法是将其重铸为float32

fmt.Println(float32(float64(float32(f)))) // = -3942.2

https://play.golang.org/p/ReIefOPEaoz

编辑:

这不是格式问题:

f := float64(-3942.2)
fmt.Println(f == float64(float32(f))) // false

编辑2:

fmt.Println(f) // -3942.2
fmt.Println(float32(f) == float32(float64(float32(f)))) // true

【问题讨论】:

    标签: go


    【解决方案1】:

    float32 的精度低于float64。两种类型都不能准确表示实数 -3942.2,但float64 更接近。

    当您转换为float32 时,该值必须四舍五入到可表示为float32 的最接近的值。丢失的信息无法恢复;转换回float64 不会重现原始值。

    第三次转换回float32,如float32(float64(float32(f))),不会恢复原始值。它看起来只是因为fmt.Println 的默认舍入行为。默认情况下,fmt.Println 将打印具有足够位数的浮点值,以将它们与其他相同类型的值区分开来。

    因为float64 具有更高的精度,所以区分float64(float32(f)) 与其他float64 值所需的小数位数大于区分float32(f)float32(float64(float32(f))) 与其他@987654336 所需的小数位数@值。

    【讨论】:

      【解决方案2】:

      它们是相同的值,只是 fmt.Println 的默认格式显示其中一个的有效数字较低,而另一个则不显示。

      比较

      https://play.golang.org/p/hJs-5Oz_YlL

      package main
      
      import (
          "fmt"
      )
      
      func main() {
          f := float64(-3942.2)
          fmt.Printf("float64(float32(f)):\t\t%.20f\n", float64(float32(f)))
      
          fmt.Printf("float32(float64(float32(f))):\t%.20f\n", float32(float64(float32(f)))) // = -3942.2
      
      }
      
      // float64(float32(f)):     -3942.19995117187500000000
      // float32(float64(float32(f))):    -3942.19995117187500000000
      

      【讨论】:

      • 它们的值不同fmt.Println(float64(float32(f)) == f) // false
      • @Chance 在您的原始帖子中,您从不直接打印 f 的值(不将其转换一次为 float32)-3942.2 不能完全存储在 float32 中,也不能在 float64 中,但在 float64 中,您将有更接近的近似值(更多数字),所以这就是它们不相等的原因。
      • @mgagnon play.golang.org/p/7q0Yq26OCBL fmt.Println(f) // -3942.2 fmt.Println(float32(f) == float32(float64(float32(f)))) // 是的
      • @Chance 这就是我所期望的。一旦在 float32 中转换,它就无法恢复丢失的精度。
      • @Chance 我的回答解释了 original 问题的输出差异。不,比较float64(float32(f)) == f 是没有意义的,因为你会失去精度。但是在你丢失它之后(就像在问题的 v1 中一样) - 它们是相同的值。来自原始问题fmt.Println(float32(f) == float32(float64(float32(f)))) // true(如预期)
      猜你喜欢
      • 2016-05-15
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多