Go

Why do these two floating-point comparisons give different results?

Question 506HardGo 1.22 to 1.25
fmt.Println(0.1+0.2 == 0.3)   // true

a, b := 0.1, 0.2
fmt.Println(a+b == 0.3)       // false
fmt.Println(a + b)            // 0.30000000000000004

const huge = 1e1000           // fine as an untyped constant
fmt.Println(huge / 1e999)     // 10

Untyped constant expressions are evaluated exactly at compile time, with at least 256-bit precision and effectively rational arithmetic for these literals. 0.1+0.2 is exactly 0.3 before it is ever converted to float64, so the first comparison is true.

Once the values are stored in float64 variables, each is rounded to the nearest binary double, and IEEE-754 addition gives 0.30000000000000004. That does not equal the double closest to 0.3, so the second comparison is false. huge cannot fit in any float type, but that only matters if it is converted. The quotient 10 fits, so the code compiles.

Takeaways: never compare floats with ==. Compare with a tolerance (math.Abs(a-b) <= eps*math.Max(math.Abs(a), math.Abs(b))). Never use floats for money; use integer cents or a decimal library. Also remember NaN != NaN, which makes a NaN map key impossible to look up again.

More on Tricky Output & Code-Review Puzzles

All 38 Tricky Output & Code-Review Puzzles questions