2016-08-12 79 views
7

我正在使用一个Django应用程序十进制的目的,并发现此奇怪的错误:甚至更神秘decimal.Decimal(n)的%1返回InvalidOperation,DivisionImpossible对于所有n> = 100

ipdb> decimal.Decimal(10) % 1 
    Decimal('0') 
ipdb> decimal.Decimal(100) % 1 
    *** decimal.InvalidOperation: [<class 'decimal.DivisionImpossible'>] 
ipdb> decimal.Decimal(150) % 1 
    *** decimal.InvalidOperation: [<class 'decimal.DivisionImpossible'>] 
ipdb> decimal.Decimal(79) % 1 
    Decimal('0') 
ipdb> decimal.Decimal(100.1) % 2 
    Decimal('0.10') 
ipdb> decimal.Decimal(1000) % 2 
    *** decimal.InvalidOperation: [<class 'decimal.DivisionImpossible'>] 

,这并未“T发生在IPython中,直到数字变得非常大:

In [23]: decimal.Decimal(10**27) % 1 
Out[23]: Decimal('0') 

In [24]: decimal.Decimal(10**28) % 1 
--------------------------------------------------------------------------- 
InvalidOperation       Traceback (most recent call last) 
<ipython-input-24-6ceaef82d283> in <module>() 
----> 1 decimal.Decimal(10**28) % 1 

InvalidOperation: [<class 'decimal.DivisionImpossible'>] 

注意,错误并不局限于IPDB:我发现了这一点,因为十进制(380)%1打破我的Django应用程序。

documentation描述这个错误说:

Division impossible

This occurs and signals invalid-operation if the integer result of a divide-integer or remainder operation had too many digits (would be longer than precision). The result is [0,qNaN].

任何想法?

+0

我无法用python 3重现你的错误,没有问题的作品 – Anonymous

+0

我无法在Python 2中重现 – dawg

+0

我可以重新编写他在Python3.5中的最后一个错误。 'Decimal(10 ** 28)%1'会抛出一个decimal.InvalidOperation:[]' –

回答

4

我想我想通了。

望着source code,我发现这一点:

# catch most cases of large or small quotient 
expdiff = self.adjusted() - other.adjusted() 
if expdiff >= context.prec + 1: 
    # expdiff >= prec+1 => abs(self/other) > 10**prec 
    return context._raise_error(DivisionImpossible) 
if expdiff <= -2: 
    # expdiff <= -2 => abs(self/other) < 0.1 
    ans = self._rescale(ideal_exponent, context.rounding) 
    return ans._fix(context) 

而在我的Django应用程序,有一个调整的PREC:

decimal.getcontext().prec = 2 

这看起来仍然小幅我错了,这是因为:

In [39]: decimal.getcontext().prec + 1 
Out[39]: 3 

In [40]: decimal.Decimal(100).adjusted() - decimal.Decimal(0).adjusted() 
Out[40]: 2 

所以它仍然看起来像100是在我的界限内t的检查(即,2 < 3),但我相当有信心,这是问题的根源。如果任何人都能为我说明图书馆为什么这么做,我希望能更好地理解它。

+0

我可以重现。 – dawg

+1

这是您正在查看的错误来源。该URL看起来像是3.2源代码。 3.5源代码将所有内容委托给['_decimal' C模块](https://hg.python.org/cpython/file/3.5/Modules/_decimal),它是[libmpdec](http:// www .bytereef.org/mpdecimal /)。 – user2357112

相关问题