繁体   English   中英

decimal.Decimal(n)%1返回InvalidOperation,DivisionImpossible所有n> = 100

[英]decimal.Decimal(n) % 1 returns InvalidOperation, DivisionImpossible for all n >= 100

我在django应用程序中使用Decimal对象,并发现了这个奇怪的错误:

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'>]

更神秘的是,在数字变得非常大之前,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:我发现这是因为Decimal(380)%1打破了我的django应用程序。

描述此错误的文档说:

分裂不可能

如果除数整数或余数运算的整数结果具有太多数字(将比精度长),则会发生这种情况并发出无效操作信号。 结果是[0,qNaN]。

有任何想法吗?

我想我明白了。

看一下源代码 ,我发现了这个:

# 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

所以看起来它仍然看起来像是在检查它的范围内(即2 < 3 ),但我相信这是问题的根源。 如果有人可以为我照亮为什么图书馆这样做,我想更好地理解它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM