As long as floating point is used, 0.1 can not be represented exactly in memory, so we know that this value usually comes out to 0.10000000000000004.
But when using go to add 0.1 and 0.2. I'm getting 0.3.
fmt.Println(0.1 + 0.2)
// Output : 0.3
Why is 0.3 coming out instead of 0.30000000000000004 ?
It is because when you print it (e.g. with the fmt
package), the printing function already rounds to a certain amount of fraction digits.
See this example:
const ca, cb = 0.1, 0.2
fmt.Println(ca + cb)
fmt.Printf("%.20f\n", ca+cb)
var a, b float64 = 0.1, 0.2
fmt.Println(a + b)
fmt.Printf("%.20f\n", a+b)
Output (try it on the Go Playground):
0.3
0.29999999999999998890
0.30000000000000004
0.30000000000000004441
First we used constants because that's different than using (non-constant) values of type float64
. Numeric constants represent exact values of arbitrary precision and do not overflow.
But when printing the result of ca+cb
, the constant value have to be converted to a non-constant, typed value to be able to be passed to fmt.Println()
. This value will be of type float64
, which cannot represent 0.3
exactly. But fmt.Println()
will round it to like ~16 fraction digits, which will be 0.3
. But when we explicitly state we want it displayed with 20 digits, we'll see it's not exact. Note that only 0.3
will be converted to float64
, because the constant arithmetic 0.1+0.2
will be evaluated by the compiler (at compile time).
Next we started with variables of type float64
, and to no surprise, output wasn't 0.3
exactly, but this time even with the default rounding we got a result different from 0.3
. The reason for this is because in the first case (constants) it was 0.3
that was converted, but this time both 0.1
and 0.2
were converted to float64
, none of which is exact, and adding them resulted in a number having bigger distance from 0.3
, big enough to make a "visual appearance" with the default rounding of the fmt
package.
Check out similar / relevant questions+answers to know more about the topic:
Why do these two float64s have different values?
How does Go perform arithmetic on constants?
Golang converting float64 to int error
Does go compiler's evaluation differ for constant expression and other expression
Why does adding 0.1 multiple times remain lossless?
Golang Round to Nearest 0.05
Go: Converting float64 to int with multiplier
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With