From ace4ee39e81a6da9e94236b5746f9ee70f8c9b95 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 17 May 2017 16:50:52 +0200 Subject: [FIX] P3: round() compatibility shim In Python 3 round: * rounds half to even (banker's rounding) rather than up * returns an int if not given a precision (or given a precision of None) * discards the negative sign when rounding to 0 Add a compatibility shim which implements P2 behaviour and at least allows passing float_utils's tests. Implementing float_round on top of Decimal was attempted but did not work: although Decimal.quantize takes a non-integral Decimal (e.g. ``d.quantize(D('0.001'))``) it only supports integral powers of 10 and does not support quantizing to e.g. 0.05: while that will not fail it will just use the exponent for quantization and 0.05 is thus equivalent to 0.01, which is not what we want if e.g. need to round a value to 5 cents. This is hinted at but maybe not clearly spelled out by the official documentation: > Return a value equal to the first operand after rounding > and **having the exponent of** the second operand. Also convert a bunch of hand-rolled currency rounding to just using the round() method on res.currency. --- 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 9c37da07fe9..d71576adc92 100644 --- a/odoo/tools/float_utils.py +++ b/odoo/tools/float_utils.py @@ -58,7 +58,7 @@ def float_round(value, precision_digits=None, precision_rounding=None, rounding_ epsilon = 2**(epsilon_magnitude-53) if rounding_method == 'HALF-UP': normalized_value += math.copysign(epsilon, normalized_value) - rounded_value = round(normalized_value) # round to integer + rounded_value = pycompat.round(normalized_value) # round to integer # TIE-BREAKING: UP (for ceiling operations) # When rounding the value up, we instead subtract the epsilon value -- cgit v1.2.3