Apply naive algorithm for huge exponents

This commit is contained in:
Sergey B Kirpichev
2026-08-20 06:18:23 +03:00
parent 0d2af59d5d
commit bc96a88926
2 changed files with 32 additions and 6 deletions
+28 -4
View File
@@ -1684,7 +1684,7 @@ def format_digits(num, format_dict, prec, rnd, _pretty_repr_dps, unique):
int_part = ''
exponent = ''
sign = ''
sign = '-' if num[0] else ''
# Now the general case
strip_last_zero = False
@@ -1720,8 +1720,33 @@ def format_digits(num, format_dict, prec, rnd, _pretty_repr_dps, unique):
frac_part = frac_part.upper()
elif unique:
# Here be dragons.
digits, exp = fpp2(num, prec, 10)
if abs(num[2] + num[3] - prec) > 10000:
dps = repr_dps(prec)
_, digits, exp = to_digits_exp(num, dps, 10)
if len(digits) > dps:
digits, exp = round_digits(num, digits, exp, dps,
10, round_nearest)
prev_digits = digits
prev_exp = exp
while True:
dps -= 1
new_digits, new_exp = round_digits(num, digits, exp, dps,
10, round_down)
new_str = f"{sign}{new_digits[0]}.{new_digits[1:]}e{exp}"
if from_str(new_str, prec, round_nearest, 10) != num:
new_digits, new_exp = round_digits(num, digits, exp, dps,
10, round_up)
new_str = f"{sign}{new_digits[0]}.{new_digits[1:]}e{exp}"
if from_str(new_str, prec, round_nearest, 10) != num:
digits = prev_digits
exp = prev_exp
break
prev_digits = new_digits
prev_exp = new_exp
else:
num = mpf_pos(num, prec, rnd) # workaround issue 1158
# Here be dragons.
digits, exp = fpp2(num, prec, 10)
split = 1
if exp < -4 or exp > prec_to_dps(prec):
@@ -1781,7 +1806,6 @@ def format_digits(num, format_dict, prec, rnd, _pretty_repr_dps, unique):
frac_part = fill_sep(frac_part, sep, frac_part[0], 1, sep_range)
digits = frac_part + exponent
sign = '-' if num[0] else ''
if sign != '-' and format_dict['sign'] != '-':
sign = format_dict['sign']
if fmt_type == 'f' and format_dict['no_neg_0']:
+4 -2
View File
@@ -129,11 +129,13 @@ def test_short_repr_roundtrip():
mp.shortest_str = True
for dps in [15, 20, 30, 50, 100, 300]:
with mp.workdps(dps):
for _ in range(10000):
for _ in range(1000):
f = random.choice([(rand()-0.5)*2 for _ in range(10)]
+ [(rand()-0.5)*2*10**5 for _ in range(5)]
+ [(rand()-0.5)*2/10**5 for _ in range(5)]
+ [(rand()-0.5)*2*10**100 for _ in range(2)])
+ [(rand()-0.5)*2*10**100 for _ in range(2)]
+ [(rand()-0.5)*2*10**10000 for _ in range(2)]
+ [(rand()-0.5)*2/10**10000 for _ in range(2)])
s = str(f)
b = mpf(s)
assert f == b # round-trip