Refactor round_digits()

* add exponent argument
* pass original number
* make inexact flag local
This commit is contained in:
Sergey B Kirpichev
2026-07-19 04:07:42 +03:00
parent 101a8379a8
commit d8c9fd2ea3
+11 -21
View File
@@ -1085,30 +1085,28 @@ def to_digits_exp(s, dps, base=10):
exponent += len(digits) - fixdps - 1
return sign, digits, exponent
def round_digits(sign, digits, dps, base, rnd=round_down, fixed=False,
inexact=False):
def round_digits(s, digits, exponent, dps, base, rnd=round_down, fixed=False):
"""
Returns the rounded digits, and the number of places the decimal point was
shifted.
``inexact`` marks that the value has a nonzero remainder past the last
supplied digit, so directed and nearest rounding round it up even when
every extracted guard digit is zero.
"""
assert len(digits) > dps
assert rnd in (round_nearest, round_up, round_down, round_ceiling,
round_floor)
sign = s[0]
# to_digits_exp truncates; flag a nonzero remainder past the last digit so
# rounding is not fooled by a short zero tail.
inexact = s[2] + len(digits) - 1 - exponent < 0
if rnd == round_ceiling:
rnd = round_down if sign else round_up
elif rnd == round_floor:
rnd = round_up if sign else round_down
exponent = 0
if rnd == round_down:
return digits[:dps], 0
return digits[:dps], exponent
elif rnd == round_nearest:
rnd_digs = stddigits[(base//2 + base % 2):base]
else:
@@ -1253,8 +1251,7 @@ def to_str(s, dps, strip_zeros=True, min_fixed=None, max_fixed=None,
n = int(digits, 16) >> shift
digits = hex(n)[2:]
digits, exp_add = round_digits(s[0], digits, dps, base, rnd)
exponent += exp_add
digits, exponent = round_digits(s, digits, exponent, dps, base, rnd)
# Prettify numbers close to unit magnitude
if not binary_exp and min_fixed < exponent < max_fixed:
@@ -1489,10 +1486,6 @@ def format_fixed(s, dps, rnd=round_down):
# exponent by +- 1)
_, digits, exponent = to_digits_exp(
s, max(dps+exponent+4, int(s[3]/blog2_10)), base)
# to_digits_exp truncates; flag a nonzero remainder past the last digit so
# rounding is not fooled by a short zero tail (#1131).
inexact = s[2] + len(digits) - 1 - exponent < 0
orig_dps = dps
dps += exponent + 1
if dps < 0:
@@ -1502,8 +1495,7 @@ def format_fixed(s, dps, rnd=round_down):
exponent -= dps
dps = 0
digits, exp_add = round_digits(s[0], digits, dps, base, rnd, True, inexact)
exponent += exp_add
digits, exponent = round_digits(s, digits, exponent, dps, base, rnd, True)
# Here we prepend the corresponding 0s to the digits string, according
# to the value of exponent
@@ -1525,8 +1517,7 @@ def format_scientific(s, dps, rnd=round_down):
_, digits, exponent = to_digits_exp(s, max(dps + 10,
int(s[3]/blog2_10) + 10),
base)
digits, exp_add = round_digits(s[0], digits, dps, base, rnd)
exponent += exp_add
digits, exponent = round_digits(s, digits, exponent, dps, base, rnd)
return digits[0], digits[1:], f'e{exponent:+03d}'
@@ -1616,8 +1607,7 @@ def format_digits(num, format_dict, prec, rnd, _pretty_repr_dps):
_, tdigits, exp = to_digits_exp(num, max(53/blog2_10, dps), 10)
if num[1]:
_, exp_add = round_digits(num, tdigits, dps, 10, rnd)
exp += exp_add
_, exp = round_digits(num, tdigits, exp, dps, 10, rnd)
fix0 = 0 if fmt_type else 1
if -4 <= exp < dps - fix0: