github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/utils/unittest/math.go (about) 1 package unittest 2 3 import ( 4 "math" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 ) 9 10 // RequireNumericallyClose is a wrapper around require.Equal that allows for a small epsilon difference between 11 // two floats. This is useful when comparing floats that are the result of a computation. For example, when comparing 12 // the result of a computation with a constant. 13 // The epsilon is calculated as: 14 // 15 // epsilon = max(|a|, |b|) * epsilon 16 // 17 // Example: 18 // 19 // RequireNumericallyClose(t, 1.0, 1.1, 0.1) // passes since 1.0 * 0.1 = 0.1 < 0.1 20 // RequireNumericallyClose(t, 1.0, 1.1, 0.01) // fails since 1.0 * 0.01 = 0.01 < 0.1 21 // RequireNumericallyClose(t, 1.0, 1.1, 0.11) // fails since 1.1 * 0.11 = 0.121 > 0.1 22 // 23 // Args: 24 // 25 // t: the testing.TB instance 26 // a: the first float 27 // b: the second float 28 func RequireNumericallyClose(t testing.TB, a, b float64, epsilon float64, msgAndArgs ...interface{}) { 29 require.True(t, AreNumericallyClose(a, b, epsilon), msgAndArgs...) 30 } 31 32 // AreNumericallyClose returns true if the two floats are within epsilon of each other. 33 // The epsilon is calculated as: 34 // 35 // epsilon = max(|a|, |b|) * epsilon 36 // 37 // Example: 38 // 39 // AreNumericallyClose(1.0, 1.1, 0.1) // true since 1.0 * 0.1 = 0.1 < 0.1 40 // AreNumericallyClose(1.0, 1.1, 0.01) // false since 1.0 * 0.01 = 0.01 < 0.1 41 // AreNumericallyClose(1.0, 1.1, 0.11) // false since 1.1 * 0.11 = 0.121 > 0.1 42 // 43 // Args: 44 // a: the first float 45 // b: the second float 46 // epsilon: the epsilon value 47 // Returns: 48 // true if the two floats are within epsilon of each other 49 // false otherwise 50 func AreNumericallyClose(a, b float64, epsilon float64) bool { 51 if a == float64(0) { 52 return math.Abs(b) <= epsilon 53 } 54 if b == float64(0) { 55 return math.Abs(a) <= epsilon 56 } 57 58 nominator := math.Abs(a - b) 59 denominator := math.Max(math.Abs(a), math.Abs(b)) 60 return nominator/denominator <= epsilon 61 }