Skip to content
Snippets Groups Projects
Commit 7b9774b9 authored by akr's avatar akr Committed by Josse Colpaert
Browse files

[IMP] base: tools: Added json_round to round into json suitable representation

X-original-commit: 415c06362c7ecea9472acf8da2ff75615eedb392
Part-of: odoo/odoo#92195
parent 3a844d81
Branches
Tags
No related merge requests found
......@@ -215,6 +215,35 @@ def float_split(value, precision_digits):
return int(units), 0
return int(units), int(cents)
def json_float_round(value, precision_digits, rounding_method='HALF-UP'):
"""Not suitable for float calculations! Similar to float_repr except that it
returns a float suitable for json dump
This may be necessary to produce "exact" representations of rounded float
values during serialization, such as what is done by `json.dumps()`.
Unfortunately `json.dumps` does not allow any form of custom float representation,
nor any custom types, everything is serialized from the basic JSON types.
:param int precision_digits: number of fractional digits to round to.
:param rounding_method: the rounding method used: 'HALF-UP', 'UP' or 'DOWN',
the first one rounding up to the closest number with the rule that
number>=0.5 is rounded up to 1, the second always rounding up and the
latest one always rounding down.
:return: a rounded float value that must not be used for calculations, but
is ready to be serialized in JSON with minimal chances of
representation errors.
"""
rounded_value = float_round(f, precision_digits=precision_digits, rounding_method=rounding_method)
rounded_repr = float_repr(rounded_value, precision_digits=precision_digits)
# As of Python 3.1, rounded_repr should be the shortest representation for our
# rounded float, so we create a new float whose repr is expected
# to be the same value, or a value that is semantically identical
# and will be used in the json serialization.
# e.g. if rounded_repr is '3.1750', the new float repr could be 3.175
# but not 3.174999999999322452.
# Cfr. bpo-1580: https://bugs.python.org/issue1580
return float(rounded_repr)
if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment