Equal returns true if a and b are equal within an absolute tolerance of Epsilon or within a relative tolerance of Epsilon (relative to the largest of the two).
(a, b float64)
| 22 | |
| 23 | // Equal returns true if a and b are equal within an absolute tolerance of Epsilon or within a relative tolerance of Epsilon (relative to the largest of the two). |
| 24 | func Equal(a, b float64) bool { |
| 25 | // avoid math.Abs |
| 26 | if a < b { |
| 27 | return b-a <= Epsilon |
| 28 | } |
| 29 | return a-b <= Epsilon |
| 30 | //return math.Abs(a-b) <= Epsilon // this is much quicker |
| 31 | |
| 32 | // See https://floating-point-gui.de/errors/comparison/ and |
| 33 | // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ |
| 34 | // for more information. To be blunt, the code below may not be appropriate for all cases, |
| 35 | // especially for small numbers. Since most comparisons involve millimeter scale (the |
| 36 | // coordinates in a canvas), this is probably OK. We should make sure that computations |
| 37 | // resulting in small numbers (below Epsilon) should be insignificant in their difference. |
| 38 | diff := math.Abs(a - b) |
| 39 | abs := a == b || diff <= Epsilon // handle infinities and absolute epsilon |
| 40 | if !abs && (a != 0.0 || b != 0.0) { |
| 41 | // handle relative epsilon for large numbers (relative to largest number) |
| 42 | return diff/math.Max(math.Abs(a), math.Abs(b)) <= Epsilon |
| 43 | } |
| 44 | return abs |
| 45 | } |
| 46 | |
| 47 | // Interval returns true if f is in closed interval [lower-Epsilon,upper+Epsilon] where lower and upper can be interchanged. |
| 48 | func Interval(f, lower, upper float64) bool { |
no outgoing calls