github.com/searKing/golang/go@v1.2.74/math/float.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package math
     6  
     7  import "math"
     8  
     9  // Epsilon very small
    10  var Epsilon = 1e-6
    11  var EpsilonClose = 1e-14
    12  var EpsilonVeryClose = 1e-16
    13  
    14  // TruncPrecision returns the float value of x, with
    15  // case n >= 0
    16  // 	the maximum n bits precision.
    17  // case n < 0
    18  //	-n bits of the magnitude of x trunked
    19  // Special cases are:
    20  //	Trunc(±0) = ±0
    21  //	Trunc(±Inf) = ±Inf
    22  //	Trunc(NaN) = NaN
    23  func TruncPrecision(x float64, n int) float64 {
    24  	n10 := math.Pow10(n)
    25  	return math.Copysign(math.Trunc((math.Abs(x)+0.5/n10)*n10)/n10, x)
    26  }
    27  
    28  // Tolerance returns true if |a-b| < e
    29  // e usually can be set with  Epsilon(1e-6)
    30  func Tolerance(a, b, e float64) bool {
    31  	// Multiplying by e here can underflow denormal values to zero.
    32  	// Check a==b so that at least if a and b are small and identical
    33  	// we say they match.
    34  	if a == b {
    35  		return true
    36  	}
    37  	d := a - b
    38  	if d < 0 {
    39  		d = -d
    40  	}
    41  
    42  	// note: b is correct (expected) value, a is actual value.
    43  	// make error tolerance a fraction of b, not a.
    44  	if b != 0 {
    45  		e = e * b
    46  		if e < 0 {
    47  			e = -e
    48  		}
    49  	}
    50  	return d < e
    51  }
    52  
    53  // Close returns true if |a-b| < 1e14
    54  func Close(a, b float64) bool { return Tolerance(a, b, EpsilonClose) }
    55  
    56  // VeryClose returns true if |a-b| < 1e16
    57  func VeryClose(a, b float64) bool { return Tolerance(a, b, EpsilonVeryClose) }
    58  
    59  // SoClose is an alias of Tolerance
    60  func SoClose(a, b, e float64) bool { return Tolerance(a, b, e) }
    61  
    62  // Alike returns true if a,b is the same exactly (no tolerance) or both NaN
    63  func Alike(a, b float64) bool {
    64  	switch {
    65  	case math.IsNaN(a) && math.IsNaN(b):
    66  		return true
    67  	case a == b:
    68  		return math.Signbit(a) == math.Signbit(b)
    69  	}
    70  	return false
    71  }