2016-08-12 77 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

相關問題