From fde3b696562a12dc3ec99fcb85004a6a40e040f0 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 7 Aug 2019 07:28:57 +0000 Subject: [FIX] tools: epsilon magnitude MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following rounding is incorrect: ``` >>> float_round(6.6 * 0.175, precision_digits=2) 1.15 ``` Indeed, 6.6 * 0.175 = 1.155 ≈ 1.16. In this specific case, the `epsilon` computed is not sufficient. A precision of 53 gives: normalized_value = 115.49999999999997 epsilon = 1.2823075934420547e-14 => new normalized_value = 115.49999999999999 Bad luck, this is just not enough to tip the value in the right direction. However, a precision of 52 is sufficient: normalized_value = 115.49999999999997 epsilon = 2.5646151868841094e-14 => new normalized_value = 115.5 The value of 53 was chosen from the `binary64` number format precision. In case of Python, the corresponding machine epsilon is 2^-52 [1]. Therefore, using 52 instead of 53 does make sense. It is worth noting that the value of the machine epsilon 2^-52 = 2.2204460492503131e-16, which is still 2 orders of magnitude below our dynamic estimation. [1] https://en.wikipedia.org/wiki/Machine_epsilon [2] `numpy.finfo(float).eps = 2.2204460492503131e-16` opw-2047368 closes odoo/odoo#35521 Signed-off-by: Nicolas Martinelli (nim) --- odoo/tools/float_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'odoo/tools/float_utils.py') diff --git a/odoo/tools/float_utils.py b/odoo/tools/float_utils.py index 041a87cabbe..eb3c0b4bd01 100644 --- a/odoo/tools/float_utils.py +++ b/odoo/tools/float_utils.py @@ -73,7 +73,7 @@ def float_round(value, precision_digits=None, precision_rounding=None, rounding_ normalized_value = value / rounding_factor # normalize sign = math.copysign(1.0, normalized_value) epsilon_magnitude = math.log(abs(normalized_value), 2) - epsilon = 2**(epsilon_magnitude-53) + epsilon = 2**(epsilon_magnitude-52) # TIE-BREAKING: UP/DOWN (for ceiling[resp. flooring] operations) # When rounding the value up[resp. down], we instead subtract[resp. add] the epsilon value -- cgit v1.2.3