355
|
1 #
|
|
2 # Determine if floating point numbers are very close
|
|
3 ###########
|
|
4
|
|
5 import math
|
|
6
|
|
7 DEFAULT_SANITY_CHECK_EPSILON = 1e-6
|
|
8
|
|
9 def floateq(a, b, epsilon=DEFAULT_SANITY_CHECK_EPSILON):
|
|
10 """
|
|
11 Compare two floats, with some epsilon tolerance.
|
|
12 """
|
|
13 return absolute_relative_error(a, b) < epsilon
|
|
14
|
|
15 def absolute_relative_error(a, b, epsilon=DEFAULT_SANITY_CHECK_EPSILON):
|
|
16 return abs(a - b) / (abs(a) + abs(b) + epsilon)
|
|
17
|
|
18 def double_epsilon_multiplicative_eq(a, b, epsilon=DEFAULT_SANITY_CHECK_EPSILON):
|
|
19 """
|
|
20 Determine if doubles are equal to within a multiplicative factor of
|
|
21 L{epsilon}.
|
|
22 @note: This function should be preferred over
|
|
23 L{double_epsilon_additive_eq}, unless the values to be compared may
|
|
24 have differing signs.
|
|
25 @precondition: sign(a) == sign(b)
|
|
26 @rtype: bool
|
|
27 """
|
|
28 if a == b: return True
|
|
29 if a == 0 and b == 0: return True
|
|
30 assert a != 0
|
|
31 assert b != 0
|
|
32 assert sign(a) == sign(b)
|
|
33 if a > b: d = a / b
|
|
34 else: d = b / a
|
|
35 assert d >= 1
|
|
36 return True if d <= 1 + SANITY_CHECK_EPSILON else False
|
|
37
|
|
38 def double_epsilon_additive_eq(a, b):
|
|
39 """
|
|
40 Determine if doubles are equal to within an additive factor of
|
|
41 L{SANITY_CHECK_EPSILON}.
|
|
42 @note: Prefer L{double_epsilon_multiplicative_eq} to this function
|
|
43 unless the values to be compared may have differing signs.
|
|
44 """
|
|
45 if a == b: return True
|
|
46 if a == 0 and b == 0: return True
|
|
47 assert sign(a) != sign(b) # Should use SANITY_CHECK_EPSILON
|
|
48 d = math.fabs(a - b)
|
|
49 return d <= SANITY_CHECK_EPSILON
|