Golang big.Float 的精度问题

Wil*_*hih 2 math biginteger go bigfloat

我遇到了 Golang big.Float 计算的一些有趣问题。

问题是

10001000100010001000100010001000100010001000100015.5533 / 1000000000000000000

= 10001000100010001000100010001000.1000100010001000155533

然而,big.Float给出了“10001000100010001000100010001000.1000100010001000155532999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 99999999999999999999999999999999999999999999999999999999999999999999997”

代码:

var prec uint = 1024 // 512
dec, _ := new(big.Float).SetPrec(prec).SetString("1000000000000000000")
f, _ := new(big.Float).SetPrec(prec).SetString("10001000100010001000100010001000100010001000100015.5533")
q := f.Quo(f, dec)

fmt.Printf("Percision: %d\n", prec)
fmt.Printf("Quotient: %s\n", q.Text('f', -1))
Run Code Online (Sandbox Code Playgroud)

结果:

Percision: 1024
Quotient: 10001000100010001000100010001000.10001000100010001555329999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997
Run Code Online (Sandbox Code Playgroud)

更令人困惑的部分是,如果我设置 prec = 512(较小的精度),它会产生正确的结果。

Percision: 512
Quotient: 10001000100010001000100010001000.1000100010001000155533
Run Code Online (Sandbox Code Playgroud)

有人知道我的代码有什么问题或者如何配置 big.Float 以获得预期结果吗?

谢谢大家!

Vol*_*ker 7

go doc math/big.Float

\n\n
\n

非零有限 Float 表示多精度浮点数

\n\n

符号 \xc3\x97 尾数 \xc3\x97 2**指数

\n\n

其中 0.5 <= 尾数 < 1.0,且 MinExp <= 指数 <= MaxExp。

\n
\n\n

SetPrec 设置尾数的位宽而不是小数精度。

\n\n

与 float64 一样,并非每个十进制数字都可以在 big.Float 中精确表示,并且您的代码显示了这一点。事实上,您看到的 prec=512 所期望的结果是由于不同的舍入和打印造成的。

\n\n

经验法则:big.Floats 的行为类似于“正常”浮点数,但有其所有缺点(这里不能表示每个小数部分),但可能显示较少的舍入误差。

\n