这个strconv.ParseFloat()的行为是预期的还是一个bug?我该如何解决这个问题?

huangapple go评论77阅读模式
英文:

Is this strconv.ParseFloat() behavior expected or a bug? How can I get around it?

问题

运行以下代码以了解我的意思:Go Playground演示问题

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变量表示。

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

我得到的结果不是4.940656458412465441765687928682213723651e-324,而是5e-324(或其非指数等价形式,您可以在Go Playground的结果中看到)。结果被四舍五入了。

有没有办法恢复回4.940656458412465441765687928682213723651e-324

或者这是一个错误吗?

英文:

Run this code to see what I mean: 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 is defined in math/const.go and I assumed it can be represented by a float64 variable.

But when it is parsed into a float64 with strconv.ParseFloat() and printed with strconv.FormatFloat() the result is rounded.

Instead of 4.940656458412465441765687928682213723651e-324 I get 5e-324 (or its non-exponent equivalent, which you can see in the Go Playground results). The result is rounded.

Is there a way to get back the 4.940656458412465441765687928682213723651e-324?

Or is it a bug?

答案1

得分: 7

这不是一个 bug。

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

英文:

This is not a bug.

You could ask Go to print more digits.

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

However, 5e-324 and 4.94…e-324 are in fact the same value, so Go is not wrong printing 5e-324. This value (2<sup>-1074</sup>) is the smallest positive number representable by Float64 (also known as double in other languages). Larger numbers are all multiples of this, e.g. the next smallest number would be 2 × 2<sup>-1074</sup> = 1e-323, the next would be 3 × 10<sup>-1074</sup> = 1.5e-323, etc.

In the other words, all numbers more precise than 5e-324 would not be representable in Float64. So it makes no sense to print more digit after the "5". And 5e-324 is certainly more readable than 4.94…e-324.

huangapple
  • 本文由 发表于 2017年3月16日 14:32:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/42826814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定