This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Sergey.Kirpichev
Recipients Sergey.Kirpichev, rhettinger, tim.peters
Date 2021-05-22.04:43:29
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <YKiL7BHSlLnclrgF@note>
In-reply-to <1621469018.51.0.202708405417.issue44154@roundup.psfhosted.org>
Content
On Thu, May 20, 2021 at 12:03:38AM +0000, Raymond Hettinger wrote:
> Raymond Hettinger <raymond.hettinger@gmail.com> added the comment:
> You're right that this won't work for decimal because it takes a
> string constructor.  A fancier reduce might do the trick but it would
> involve modifying the C code (no fun) as well as the Python code.

Yes, it will be harder.  But I think - is possible.

E.g. with this trivial patch:
$ git diff
diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py
index ff23322ed5..473fb86770 100644
--- a/Lib/_pydecimal.py
+++ b/Lib/_pydecimal.py
@@ -627,6 +627,9 @@ def __new__(cls, value="0", context=None):
                 self._exp = value[2]
                 self._is_special = True
             else:
+                value = list(value)
+                if isinstance(value[1], int):
+                    value[1] = tuple(map(int, str(value[1])))
                 # process and validate the digits in value[1]
                 digits = []
                 for digit in value[1]:
@@ -3731,7 +3734,7 @@ def shift(self, other, context=None):

     # Support for pickling, copy, and deepcopy
     def __reduce__(self):
-        return (self.__class__, (str(self),))
+        return (self.__class__, ((self._sign, int(self._int), self._exp),))

     def __copy__(self):
         if type(self) is Decimal:

Simple test suggests that 2x size difference is possible:
>>> import pickle
>>> from test.support.import_helper import import_fresh_module
>>> P = import_fresh_module('decimal', blocked=['_decimal'])
>>> P.getcontext().prec = 1000
>>> d = P.Decimal('101').exp()
>>> len(pickle.dumps(d))
1045

vs
>>> len(pickle.dumps(d))
468

with the above diff.  (Some size reduction will be even if we
don't convert back and forth the self._int, due to self._exp size.
This is a less interesting case, but it's for free!  No speed penalty.)

> Also, the conversion from decimal to string and back isn't quadratic,
> so we don't have the same worries.

Yes, for a speed bonus - we need to do something more clever)

> Lastly, really large fractions happen naturally as they interoperate,
> but oversized decimals are uncommon.

For financial calculations this, probably, is true.  But perfectly
legal usage of this module - to compute mathematical functions with
arbitrary-precision (like mpmath does with mpmath.mpf).

Let me know if it's worth openning an issue with above improvement.
History
Date User Action Args
2021-05-22 04:43:30Sergey.Kirpichevsetrecipients: + Sergey.Kirpichev, tim.peters, rhettinger
2021-05-22 04:43:30Sergey.Kirpichevlinkissue44154 messages
2021-05-22 04:43:29Sergey.Kirpichevcreate