github.com/searKing/golang/go@v1.2.117/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  //
    17  //	the maximum n bits precision.
    18  //
    19  // case n < 0
    20  //
    21  //	-n bits of the magnitude of x trunked
    22  //
    23  // Special cases are:
    24  //
    25  //	Trunc(±0) = ±0
    26  //	Trunc(±Inf) = ±Inf
    27  //	Trunc(NaN) = NaN
    28  func TruncPrecision(x float64, n int) float64 {
    29  	n10 := math.Pow10(n)
    30  	return math.Copysign(math.Trunc((math.Abs(x)+0.5/n10)*n10)/n10, x)
    31  }
    32  
    33  // Tolerance returns true if |a-b| < e
    34  // e usually can be set with  Epsilon(1e-6)
    35  func Tolerance(a, b, e float64) bool {
    36  	// Multiplying by e here can underflow denormal values to zero.
    37  	// Check a==b so that at least if a and b are small and identical
    38  	// we say they match.
    39  	if a == b {
    40  		return true
    41  	}
    42  	d := a - b
    43  	if d < 0 {
    44  		d = -d
    45  	}
    46  
    47  	// note: b is correct (expected) value, a is actual value.
    48  	// make error tolerance a fraction of b, not a.
    49  	if b != 0 {
    50  		e = e * b
    51  		if e < 0 {
    52  			e = -e
    53  		}
    54  	}
    55  	return d < e
    56  }
    57  
    58  // Close returns true if |a-b| < 1e14
    59  func Close(a, b float64) bool { return Tolerance(a, b, EpsilonClose) }
    60  
    61  // VeryClose returns true if |a-b| < 1e16
    62  func VeryClose(a, b float64) bool { return Tolerance(a, b, EpsilonVeryClose) }
    63  
    64  // SoClose is an alias of Tolerance
    65  func SoClose(a, b, e float64) bool { return Tolerance(a, b, e) }
    66  
    67  // Alike returns true if a,b is the same exactly (no tolerance) or both NaN
    68  func Alike(a, b float64) bool {
    69  	switch {
    70  	case math.IsNaN(a) && math.IsNaN(b):
    71  		return true
    72  	case a == b:
    73  		return math.Signbit(a) == math.Signbit(b)
    74  	}
    75  	return false
    76  }