Make MinMax return NaN when all values are NaN

Signed-off-by: Xabier Larrakoetxea <slok69@gmail.com>
This commit is contained in:
Xabier Larrakoetxea 2019-04-17 13:40:32 +02:00
parent 6cf2caf0b6
commit 9b25e35172
No known key found for this signature in database
GPG Key ID: FDAD7FD8275E1B32
2 changed files with 21 additions and 2 deletions

View File

@ -109,17 +109,20 @@ func Round(x float64) float64 {
// MinMax returns the smallest and the largest value among the provided values.
// Returns (0, 0) if there are no values.
// Ignores NaN values.
// Ignores NaN values. Allowing NaN values could led in a corner case where all
// values can be NaN, in this case the function will return NaN as min and max.
func MinMax(values []float64) (min, max float64) {
if len(values) == 0 {
return 0, 0
}
min = math.MaxFloat64
max = -1 * math.MaxFloat64
allNaN := true
for _, v := range values {
if math.IsNaN(v) {
continue
}
allNaN = false
if v < min {
min = v
@ -128,6 +131,11 @@ func MinMax(values []float64) (min, max float64) {
max = v
}
}
if allNaN {
return math.NaN(), math.NaN()
}
return min, max
}

View File

@ -221,12 +221,23 @@ func TestMinMax(t *testing.T) {
wantMin: -11.3,
wantMax: 22.5,
},
{
desc: "all NaN values",
values: []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN()},
wantMin: math.NaN(),
wantMax: math.NaN(),
},
}
for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
gotMin, gotMax := MinMax(tc.values)
if gotMin != tc.wantMin || gotMax != tc.wantMax {
// Different assertion for NaN cases.
if (math.IsNaN(tc.wantMin) && !math.IsNaN(gotMin)) ||
(math.IsNaN(tc.wantMax) && !math.IsNaN(gotMax)) {
t.Errorf("MinMax => (%v, %v), want (%v, %v)", gotMin, gotMax, tc.wantMin, tc.wantMax)
} else if !math.IsNaN(tc.wantMin) && gotMin != tc.wantMin ||
!math.IsNaN(tc.wantMax) && gotMax != tc.wantMax {
t.Errorf("MinMax => (%v, %v), want (%v, %v)", gotMin, gotMax, tc.wantMin, tc.wantMax)
}
})