How do you preserve precision when scaling a Decimal?
<p>How can you scale a <a href="https://docs.python.org/library/decimal.html#decimal.Decimal" rel="nofollow"><code>Decimal</code></a>, but keep its original precision? E.g.,</p>

<pre><code>&gt;&gt;&gt; from decimal import Decimal
&gt;&gt;&gt; Decimal('0.1230')
Decimal('0.1230') # Precision is 4.
</code></pre>

<p>Multiplication does not preserve the original precision:</p>

<pre><code>&gt;&gt;&gt; Decimal('0.1230') * 100
Decimal('12.3000') #  Precision is 6.
&gt;&gt;&gt; Decimal('0.1230') * Decimal('100')
Decimal('12.3000') # Precision is 6.
</code></pre>

<p>The <a href="https://docs.python.org/library/decimal.html#decimal.Decimal.shift" rel="nofollow"><code>.shift()</code></a> method only keeps the same number of decimal places when shifting by a negative amount:</p>

<pre><code>&gt;&gt;&gt; Decimal('0.1230').shift(2)
Decimal('12.3000') # Precision is 6.
&gt;&gt;&gt; Decimal('0.1230').shift(-2)
Decimal('0.0012') # Precision is 2.
</code></pre>

<p>From the answer, <a href="http://stackoverflow.com/a/33948596/47078">http://stackoverflow.com/a/33948596/47078</a>, you could do something like the following. I'm not sure, though, if what you want is possible without additional code: namely to have a Decimal that preserves precision automatically.</p>

<pre><code>&gt;&gt;&gt; import decimal
&gt;&gt;&gt; f = decimal.Context(prec=4).create_decimal('0.1230')
&gt;&gt;&gt; f
Decimal('0.1230')
&gt;&gt;&gt; decimal.Context(prec=4).create_decimal(f * 100)
Decimal('12.30')
</code></pre>

<p>You may want to write your own class or helper methods to make it look nicer.</p>

<pre><code>&gt;&gt;&gt; Decimal4 = decimal.Context(prec=4).create_decimal
&gt;&gt;&gt; Decimal4('0.1230')
Decimal('0.1230')
&gt;&gt;&gt; Decimal4(Decimal4('0.1230') * 100)
Decimal('12.30')
</code></pre>

<p>Looks like (from <a href="https://docs.python.org/2/library/decimal.html#decimal.Context.create_decimal" rel="nofollow">decimal.Context.create_decimal</a>) you can also do it this way:</p>

<pre><code># This is copied verbatim from the Python documentation
&gt;&gt;&gt; getcontext().prec = 3
&gt;&gt;&gt; Decimal('3.4445') + Decimal('1.0023')
Decimal('4.45')
&gt;&gt;&gt; Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
</code></pre>

<p>Perhaps you could create a method to replace Decimal() that creates the Decimal object, and updates the global precision if the current precision is less than the current.</p>

<pre><code>&gt;&gt;&gt; def make_decimal(value):
...     number = decimal.Decimal(value)
...     prec = len(number.as_tuple().digits)
...     if prec &lt; decimal.getcontext().prec:
...         decimal.getcontext().prec = prec
...     return number
...
&gt;&gt;&gt; make_decimal('0.1230')
Decimal('0.1230')
&gt;&gt;&gt; make_decimal('0.1230') * 100
Decimal('12.30')
</code></pre>

<p>You would then want a <code>reset_decimal_precision</code> method or an optional parameter to <code>make_decimal</code> to do the same so you could start new calculations. The downside is that it limits you to only one global precision at a time. I think the best solution might be to subclass Decimal() and make it keep track of precision.</p>

python python-2.7