这是strconv.ParseFloat()预期的行为还是一个错误?我怎么能绕过它呢?

时间:2017-03-16 06:32:19

标签: go

运行此代码以查看我的意思: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))
}

SmallestNonzeroFloat64math/const.go中定义,我认为它可以用float64变量表示。

但是当它被解析为带有strconv.ParseFloat()并使用strconv.FormatFloat()打印的float64时,结果会被舍入。

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

有没有办法取回4.940656458412465441765687928682213723651e-324

或者它是一个错误?

1 个答案:

答案 0 :(得分:7)

这不是错误。

你可以要求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更具可读性。