1 // Untyped float constants are exact rationals, not rounded float64s - in one
2 // package and across the .mxh boundary.
3 //
4 // stage4 compared `constEqual`'s rounded float64, and exported a folded
5 // constant as its shortest round-tripping decimal. Both made
6 // `math.MaxFloat64 == 1.7976931348623157e308` true: the decimal rounds to the
7 // binary value, so the two constants were indistinguishable after rounding.
8 // go/types (the legacy compiler) compares the exact rationals and says false.
9 package main
10 11 import (
12 "fmt"
13 "math"
14 )
15 16 // The exact expression, in-package: 2^1023 * (1 + (1 - 2^-52)).
17 const maxExpr = 0x1p1023 * (1 + (1 - 0x1p-52))
18 19 func main() {
20 // Across packages: the exported constant carries its exact value, so the
21 // decimal that merely rounds to it is a different number.
22 if math.MaxFloat64 == 1.7976931348623157e308 {
23 panic("math.MaxFloat64 equals the decimal that rounds to it")
24 }
25 if !(math.MaxFloat64 == 0x1p1023*(1+(1-0x1p-52))) {
26 panic("math.MaxFloat64 is not the value of its exact expression")
27 }
28 // The same two comparisons from inside the defining package.
29 if maxExpr == 1.7976931348623157e308 {
30 panic("the exact expression equals the decimal that rounds to it")
31 }
32 if !(maxExpr == 0x1p1023*(1+(1-0x1p-52))) {
33 panic("identical expressions are not equal")
34 }
35 // Constant arithmetic is exact, so these follow go/types, not float64:
36 // 0.1+0.2 is 3/10 exactly, and 1/3 is not the 16-digit decimal.
37 if !(0.1+0.2 == 0.3) {
38 panic("0.1+0.2 must equal 0.3 exactly")
39 }
40 if 1.0/3.0 == 0.3333333333333333 {
41 panic("1/3 must not equal the 16-digit decimal")
42 }
43 if !(1.0/3.0*3.0 == 1.0) {
44 panic("1/3*3 must equal 1 exactly")
45 }
46 if math.MaxFloat64/2 == math.MaxFloat64 {
47 panic("MaxFloat64/2 is not MaxFloat64")
48 }
49 fmt.Println("ok")
50 }
51