运行以下代码,了解我的意思:Go Playground demo of issue

package main

import (
    "fmt"
    "strconv"
)

func main() {
    // From https://golang.org/src/math/const.go
    var SmallestNonzeroFloat64AsString string = "4.940656458412465441765687928682213723651e-324"
    var SmallestNonzeroFloat64 float64
    var err error
    SmallestNonzeroFloat64, err = strconv.ParseFloat(SmallestNonzeroFloat64AsString, 64)
    if err != nil {
        panic(err)
    }
    fmt.Printf("SmallestNonzeroFloat64 = %g\n", SmallestNonzeroFloat64)
    fmt.Printf("SmallestNonzeroFloat64 = %s\n", strconv.FormatFloat(SmallestNonzeroFloat64, 'f', -1, 64))
}
SmallestNonzeroFloat64是在math/const.go中定义的,我假设它可以由float64变量表示。

但是,当使用strconv.ParseFloat()将其解析为float64并使用strconv.FormatFloat()打印时,结果将四舍五入。

我得到的不是4.940656458412465441765687928682213723651e-324,而是5e-324(或它的非指数等效物,您可以在Go Playground结果中看到)。结果四舍五入。

有办法找回4.940656458412465441765687928682213723651e-324吗?

还是一个错误?

最佳答案

这不是错误。

您可以要求Go打印更多数字。

fmt.Printf("SmallestNonzeroFloat64 = %.40g\n", SmallestNonzeroFloat64)
// 4.940656458412465441765687928682213723651e-324

但是,5e-3244.94…e-324实际上是相同的值,因此Go打印5e-324并没有错。此值(2-1074)是Float64表示的最小正数(在其他语言中也称为double)。较大的数字都是此的倍数,例如下一个最小的数字将是2×2-1074 = 1e-323,下一个将是3×10-1074 = 1.5e-323,依此类推。

换句话说,比5e-324更精确的所有数字都无法在Float64中表示出来。因此,在“5”之后再打印更多数字是没有意义的。而且5e-324当然比4.94…e-324更具可读性。

关于go - 这是strconv.ParseFloat()行为的预期还是错误?我该如何解决?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42826814/

10-11 09:13