From dc52c7fe0a1e248c443a24fb81f4b3f0c509e17c Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Fri, 19 Nov 2021 16:41:40 +0200 Subject: [PATCH] (core) Add PY2_ROUND function for easier migration Summary: As discussed in https://github.com/dsagal/grist-help/pull/112 Test Plan: doctest in function Reviewers: paulfitz, dsagal Reviewed By: paulfitz Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D3147 --- sandbox/grist/functions/math.py | 29 +++++++++++++++++++++-------- sandbox/grist/functions/text.py | 5 +++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/sandbox/grist/functions/math.py b/sandbox/grist/functions/math.py index 09e5ed59..9f205c31 100644 --- a/sandbox/grist/functions/math.py +++ b/sandbox/grist/functions/math.py @@ -600,12 +600,20 @@ def ROMAN(number, form_unused=None): def ROUND(value, places=0): """ - Rounds a number to a certain number of decimal places according to standard rules. + Rounds a number to a certain number of decimal places, + by default to the nearest whole number if the number of places is not given. - >>> ROUND(2.15, 1) # Excel actually gives the more correct 2.2 - 2.1 - >>> ROUND(2.149, 1) - 2.1 + Rounds away from zero ('up' for positive numbers) + in the case of a tie, i.e. when the last digit is 5. + + >>> ROUND(1.4) + 1.0 + >>> ROUND(1.5) + 2.0 + >>> ROUND(2.5) + 3.0 + >>> ROUND(2.15, 1) + 2.2 >>> ROUND(-1.475, 2) -1.48 >>> ROUND(21.5, -1) @@ -616,10 +624,15 @@ def ROUND(value, places=0): 0.0 >>> ROUND(-50.55,-2) -100.0 + >>> ROUND(0) + 0.0 """ - # TODO: Excel manages to round 2.15 to 2.2, but Python sees 2.149999... and rounds to 2.1 - # (see Python notes in documentation of `round()`). - return round(value, places) + p = 10 ** places + if value >= 0: + return float(_math.floor((value * p) + 0.5)) / p + else: + return float(_math.ceil((value * p) - 0.5)) / p + def ROUNDDOWN(value, places=0): """ diff --git a/sandbox/grist/functions/text.py b/sandbox/grist/functions/text.py index 35c588ac..ee9a3b15 100644 --- a/sandbox/grist/functions/text.py +++ b/sandbox/grist/functions/text.py @@ -10,6 +10,7 @@ from six import unichr from six.moves import xrange from usertypes import AltText # pylint: disable=import-error +from .math import ROUND from .unimplemented import unimplemented @@ -120,7 +121,7 @@ def DOLLAR(number, decimals=2): >>> DOLLAR(10, 0) '$10' """ - formatted = "${:,.{}f}".format(round(abs(number), decimals), max(0, decimals)) + formatted = "${:,.{}f}".format(ROUND(abs(number), decimals), max(0, decimals)) return formatted if number >= 0 else "(" + formatted + ")" @@ -195,7 +196,7 @@ def FIXED(number, decimals=2, no_commas=False): '3500' """ comma_flag = '' if no_commas else ',' - return "{:{}.{}f}".format(round(number, decimals), comma_flag, max(0, decimals)) + return "{:{}.{}f}".format(ROUND(number, decimals), comma_flag, max(0, decimals)) def LEFT(string, num_chars=1):