Skip to content

Commit 3498027

Browse files
committed
math: increase precision of math.SmallestNonzeroFloat64
The original value was rounded too early, which lead to the surprising behavior that float64(math.SmallestNonzeroFloat64 / 2) wasn't 0. That is, the exact compile-time computation of math.SmallestNonzeroFloat64 / 2 resulted in a value that was rounded up when converting to float64. To address this, added 3 more digits to the mantissa, ending in a 0. While at it, also slightly increased the precision of MaxFloat64 to end in a 0. Computed exact values via https://play.golang.org/p/yt4KTpIx_wP. Added a test to verify expected behavior. In contrast to the other (irrational) constants, expanding these extreme values to more digits is unlikely to be important as they are not going to appear in numeric computations except for tests verifying their correctness (as is the case here). Re-enabled a disabled test in go/types and types2. Updates #44057. Fixes #44058. Change-Id: I8f363155e02331354e929beabe993c8d8de75646 Reviewed-on: https://go-review.googlesource.com/c/go/+/315170 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 02ab8d1 commit 3498027

File tree

5 files changed

+23
-12
lines changed

5 files changed

+23
-12
lines changed

api/except.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
2+
pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3+
pkg math, const SmallestNonzeroFloat64 = 4.94066e-324 // 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
24
pkg math/big, const MaxBase = 36
35
pkg math/big, type Word uintptr
46
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)

src/cmd/compile/internal/types2/testdata/check/const1.src

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package const1
88

9+
import "math"
10+
911
const(
1012
mi = ^int(0)
1113
mu = ^uint(0)
@@ -48,7 +50,7 @@ const (
4850
// without overflow. For now we match the compiler.
4951
// See also issue #44057.
5052
// smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
51-
smallestFloat64 = 4.940656458412465441765687928682213723651e-324
53+
smallestFloat64 = math.SmallestNonzeroFloat64
5254
)
5355

5456
const (
@@ -63,7 +65,7 @@ const (
6365
// without overflow. For now we match the compiler.
6466
// See also issue #44057.
6567
// maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
66-
maxFloat64 = 1.797693134862315708145274237317043567981e+308
68+
maxFloat64 = math.MaxFloat64
6769
)
6870

6971
const (
@@ -281,9 +283,7 @@ const (
281283
_ = assert(float64(smallestFloat32) == smallestFloat32)
282284
_ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
283285
_ = assert(float64(smallestFloat64) == smallestFloat64)
284-
// TODO(gri) With the change to the declaration of smallestFloat64
285-
// this now fails to be true. See issue #44058.
286-
// _ = assert(float64(smallestFloat64/2) == 0)
286+
_ = assert(float64(smallestFloat64/2) == 0)
287287
)
288288

289289
const (

src/go/types/testdata/check/const1.src

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package const1
88

9+
import "math"
10+
911
const(
1012
mi = ^int(0)
1113
mu = ^uint(0)
@@ -48,7 +50,7 @@ const (
4850
// without overflow. For now we match the compiler.
4951
// See also issue #44057.
5052
// smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
51-
smallestFloat64 = 4.940656458412465441765687928682213723651e-324
53+
smallestFloat64 = math.SmallestNonzeroFloat64
5254
)
5355

5456
const (
@@ -63,7 +65,7 @@ const (
6365
// without overflow. For now we match the compiler.
6466
// See also issue #44057.
6567
// maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
66-
maxFloat64 = 1.797693134862315708145274237317043567981e+308
68+
maxFloat64 = math.MaxFloat64
6769
)
6870

6971
const (
@@ -281,9 +283,7 @@ const (
281283
_ = assert(float64(smallestFloat32) == smallestFloat32)
282284
_ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
283285
_ = assert(float64(smallestFloat64) == smallestFloat64)
284-
// TODO(gri) With the change to the declaration of smallestFloat64
285-
// this now fails to be true. See issue #44058.
286-
// _ = assert(float64(smallestFloat64/2) == 0)
286+
_ = assert(float64(smallestFloat64/2) == 0)
287287
)
288288

289289
const (

src/math/all_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,15 @@ func TestFloatMinMax(t *testing.T) {
31963196
}
31973197
}
31983198

3199+
func TestFloatMinima(t *testing.T) {
3200+
if q := float32(SmallestNonzeroFloat32 / 2); q != 0 {
3201+
t.Errorf("float32(SmallestNonzeroFloat32 / 2) = %g, want 0", q)
3202+
}
3203+
if q := float64(SmallestNonzeroFloat64 / 2); q != 0 {
3204+
t.Errorf("float64(SmallestNonzeroFloat64 / 2) = %g, want 0", q)
3205+
}
3206+
}
3207+
31993208
var indirectSqrt = Sqrt
32003209

32013210
// TestFloat32Sqrt checks the correctness of the float32 square root optimization result.

src/math/const.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ const (
3131
MaxFloat32 = 3.40282346638528859811704183484516925440e+38 // 2**127 * (2**24 - 1) / 2**23
3232
SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)
3333

34-
MaxFloat64 = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
35-
SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
34+
MaxFloat64 = 1.79769313486231570814527423731704356798070e+308 // 2**1023 * (2**53 - 1) / 2**52
35+
SmallestNonzeroFloat64 = 4.9406564584124654417656879286822137236505980e-324 // 1 / 2**(1023 - 1 + 52)
3636
)
3737

3838
// Integer limit values.

0 commit comments

Comments
 (0)