Go:为啥从 float64 转换为 float32 并返回会导致值发生变化? [复制]

Posted

技术标签:

【中文标题】Go:为啥从 float64 转换为 float32 并返回会导致值发生变化? [复制]【英文标题】: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

【问题讨论】:

【参考方案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(如预期)

以上是关于Go:为啥从 float64 转换为 float32 并返回会导致值发生变化? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Pandas 将我的 numpy float32 强制转换为 float64?

Go语言数组,切片

为啥Go中有int但没有float?

Go语言string,int,int64 ,float之间类型转换方法

go语言之类型转换

go笔记 - 字符串、数字、byte相互转换