user41804
user41804

Reputation: 19

How to store a big float64 in a string without overflow?

func main() {
        target := 20190201518310870.0
        fmt.Println(int64(target))
        z3 := big.NewInt(int64(target))
        fmt.Println(z3)
}

The result is 20190201518310872

How do I convert it and not make overflow?

Upvotes: 0

Views: 1057

Answers (1)

icza
icza

Reputation: 418137

The problem is that even your input target number is not equal to the constant you assign to it.

The float64 type uses the double-precision floating-point format (IEEE 754) to store the number, which has finite bits to utilize (64 bits in total, but only 53 bits are used to store the significand). This means it can roughly store ~16 digits, but your input number has 17, so it will be rounded to the nearest representable float64.

If you print target, you will see the exact number that is "transfered" to big.Int:

target := 20190201518310870.0
fmt.Printf("%f\n", target)

Outputs (try it on the Go Playground):

20190201518310872.000000

Note that it works if the input constant "fits" into float64:

target := 20190201518310.0
fmt.Printf("%f\n", target)
fmt.Println(int64(target))
z3 := big.NewInt(int64(target))
fmt.Println(z3)

Outputs (try it on the Go Playground):

20190201518310.000000
20190201518310
20190201518310

If you need to work with big numbers exactly such as 20190201518310870.0, you have to use another type to store it in the first place, e.g. string, big.Int or big.Float, but not float64.

For example:

target := "20190201518310870"
fmt.Println(target)
z3, ok := big.NewInt(0).SetString(target, 10)
fmt.Println(z3, ok)

Output (try it on the Go Playground):

20190201518310870
20190201518310870 true

Upvotes: 3

Related Questions