Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a123631

Browse files
committed
Fix a performance issue in Decimal.pow. Thanks Stefan Krah for finding this.
1 parent f48ea7c commit a123631

3 files changed

Lines changed: 25 additions & 6 deletions

File tree

Lib/decimal.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,12 +2047,14 @@ def _power_exact(self, other, p):
20472047
# case where xc == 1: result is 10**(xe*y), with xe*y
20482048
# required to be an integer
20492049
if xc == 1:
2050-
if ye >= 0:
2051-
exponent = xe*yc*10**ye
2052-
else:
2053-
exponent, remainder = divmod(xe*yc, 10**-ye)
2054-
if remainder:
2055-
return None
2050+
xe *= yc
2051+
# result is now 10**(xe * 10**ye); xe * 10**ye must be integral
2052+
while xe % 10 == 0:
2053+
xe //= 10
2054+
ye += 1
2055+
if ye < 0:
2056+
return None
2057+
exponent = xe * 10**ye
20562058
if y.sign == 1:
20572059
exponent = -exponent
20582060
# if other is a nonnegative integer, use ideal exponent

Lib/test/decimaltestdata/extra.decTest

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,20 @@ extr1658 shift 1234567 3 -> 7000
213213
extr1659 shift 1234567 4 -> 0
214214
extr1660 shift 1234567 5 -> NaN Invalid_operation
215215

216+
-- Cases where the power function was impossibly slow to determine that the
217+
-- result is inexact. Thanks Stefan Krah for identifying this problem.
218+
precision: 16
219+
maxExponent: 999999999
220+
minExponent: -999999999
221+
extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded
222+
extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded
223+
extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded
216224

225+
-- A couple of interesting exact cases for power. Note that the specification
226+
-- requires these to be reported as Inexact.
227+
extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded
228+
extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded
229+
extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded
217230

218231
-- Tests for the is_* boolean operations
219232
precision: 9

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ C-API
470470
Library
471471
-------
472472

473+
- Fix extreme speed issue in Decimal.pow when the base is an exact
474+
power of 10 and the exponent is tiny (for example,
475+
Decimal(10) ** Decimal('1e-999999999')).
476+
473477
- Issue #9186: Fix math.log1p(-1.0) to raise ValueError, not OverflowError.
474478

475479
- Issue #9130: Fix validation of relative imports in parser module.

0 commit comments

Comments
 (0)