简体   繁体   English

big.Float SetPrec怪异的行为

[英]big.Float SetPrec weird behaviour

After doing some calculations using big.Float in golang, I am setting the precision to 2. 在golang中使用big.Float进行了一些计算之后,我将精度设置为2。

And even thou the number is just a simple 10, after setting the precision it is 8. 甚至您的数字只是一个简单的10,将精度设置为8之后。

package main

import (
    "fmt"
    "math/big"
)

func main() {
    cost := big.NewFloat(10)
    fmt.Println("COST NOW", cost)

    perKWh := big.NewFloat(0)
    cost.Add(cost, perKWh)
    fmt.Println("COST ", cost.String())

    perMinute := big.NewFloat(0)
    cost.Add(cost, perMinute)
    fmt.Println("COST ", cost.String())

    discountAmount := big.NewFloat(0)
    cost.Sub(cost, discountAmount)
    floatCos, _ := cost.Float64()
    fmt.Println(fmt.Sprintf("COST FLOAT %v", floatCos))
    cost.SetPrec(2)

    fmt.Println("COST ", cost.String())
}

Check playground example here: https://play.golang.org/p/JmCRXkD5u49 在此处查看游乐场示例: https : //play.golang.org/p/JmCRXkD5u49

Would like to understand why 想了解为什么

From the fine manual : 精美的手册中

type Float 浮动类型
[...] [...]
Each Float value also has a precision, rounding mode, and accuracy. 每个浮点值还具有精度,舍入模式和精度。 The precision is the maximum number of mantissa bits available to represent the value. 精度是可用于表示该值的最大尾数位数。 The rounding mode specifies how a result should be rounded to fit into the mantissa bits, and accuracy describes the rounding error with respect to the exact result. 舍入模式指定如何将结果舍入以适合尾数位,而精度描述相对于精确结果的舍入误差。

And big.Float is represented internally as: 并且big.Float内部表示为:

sign × mantissa × 2**exponent

When you call SetPrec you're setting the number of bits available for the mantissa, not the number of digits of precision in the decimal representation of the number. 当你调用SetPrec你设置可用于尾数的精度数的十进制表示数字不是数字的位数

You can't represent decimal 10 (1010 binary) in two bits of mantissa so it rounds to decimal 8 (1000 binary) which can fit into 2 bits. 您无法在尾数的两位中表示十进制10(1010二进制),因此将其舍入为可以容纳2位的十进制8(1000二进制)。 You need at least three bits to store the 101 part of decimal 10. 8 can fit into a single bit of mantissa so you'll see the same 8 if you say cost.SetPrec(1) . 您至少需要三位来存储十进制10的101部分。8可以放入一个尾数位,因此,如果您说cost.SetPrec(1) ,您将看到相同的8。

You need to be thinking in terms of binary when using the big package. 使用大包时,您需要考虑二进制。

First, discard all the irrelevant code. 首先,丢弃所有不相关的代码。 Next, print useful diagnostic information. 接下来,打印有用的诊断信息。

package main

import (
    "fmt"
    "math/big"
)

func main() {
    cost := big.NewFloat(10)
    fmt.Println("Cost ", cost.String())
    fmt.Println("Prec", cost.Prec())
    fmt.Println("MinPrec", cost.MinPrec())
    fmt.Println("Mode", cost.Mode())
    cost.SetPrec(2)
    fmt.Println("Prec", cost.Prec())
    fmt.Println("Accuracy", cost.Acc())
    fmt.Println("Cost ", cost.String())
}

Output: 输出:

Cost  10
Prec 53
MinPrec 3
Mode ToNearestEven
Prec 2
Accuracy Below
Cost  8

Round 10 to the nearest even number that can be represented in an sign, exponent, and a 2-bit mantissa and you get 8. 将10舍入到可以用符号,指数和2位尾数表示的最接近的偶数,得到8。

Rounding ToNearestEven is IEE754 rounding. 四舍五入到最接近甚至是IEE754舍入。 Round to nearest, ties to even – rounds to the nearest value; 四舍五入到最接近的值,并保持偶数–四舍五入到最近的值; if the number falls midway it is rounded to the nearest value with an even (zero) least significant bit. 如果该数字落在中间,则使用偶数(零)最低有效位四舍五入到最接近的值。

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

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