简体   繁体   English

golang在将float32转换为float64时失去精度?

[英]golang losing precision while converting float32 to float64?

In Golang, it seems that when a float64 var first convert to float32 then convert float64, it's value will change.在 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

How can I make it unchanging我怎样才能让它不变

The way you have described the problem is perhaps misleading.您描述问题的方式可能具有误导性。

The precision is not lost "when converting float32 to float64"; “将float32转换为float64时”不会丢失精度; rather, it is lost when converting from float64 to float32.相反,它在从 float64 转换为 float32 时会丢失。

So how can you avoid losing precision when converting from float64 to float32?那么如何在从 float64 转换为 float32 时避免丢失精度呢? You can't.你不能。 This task is impossible, and it's quite easy to see the reason why:这个任务是不可能的,很容易看出原因:

  • float64 has twice as many bits as float32 float64 的位数是 float32 的两倍
  • multiple different float64 values will map to the same float32 value due to the pigeonhole principle由于鸽巢原理,多个不同的 float64 值将 map 变为相同的 float32 值
  • the conversion is therefore not reversible.因此,转换是不可逆的。
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)))
}

Adjusting your program to show a more precise output of each value, you'll see exactly where the precision is lost:调整您的程序以显示每个值的更精确的 output,您将确切地看到精度丢失的位置:

-8888.95000000000072759576
-8888.95019531250000000000
-8888.95019531250000000000

That is, after the float32 conversion (as is expected).也就是说,在 float32 转换之后(如预期的那样)。

It's also worth noting that neither float64 nor float32 can represent your value -8888.95 exactly.还值得注意的是,float64 和 float32不能准确地代表您的值 -8888.95。 If you convert this number to a fraction, you will get -177779/20 .如果将此数字转换为分数,您将得到-177779/20 Notice the denominator, 20. The prime factorization of 20 is 2 * 2 * 5.注意分母 20。20 的素数分解是 2 * 2 * 5。

If you apply this process to a number and the prime factorization of the denominator contains any factors which are NOT 2, then you can rest assured that this number is definitely not representable exactly in binary floating point form.如果您将此过程应用于一个数字并且分母的素数分解包含任何不是 2 的因子,那么您可以确保该数字绝对不能以二进制浮点形式精确表示。 You may discover that the probability of any number passing this test is quite low.您可能会发现任何数字通过此测试的概率非常低。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM