浮点精度会在比较期间导致错误

时间:2014-03-10 17:11:44

标签: python floating-point

我正在使用python 2.7.6。当我在解释器中键入它时

>>> 0.135-0.027
0.10800000000000001

它应该只是

0.108

这会在比较事物时引起问题,例如我想比较

>>> 0.135-0.027 <= 0.108
False

我希望这个答案为真。我是否必须使用能够正确处理浮子的特殊包装?有没有办法以另一种方式解决这个问题?例如,我们可以使用

强制浮动除法
from __future__ import division

这个问题是否有类似的解决方案?

2 个答案:

答案 0 :(得分:2)

你可以做各种各样的事情,但每种都有各自的优点和缺点。

基本问题是从十进制到任何有限二进制表示的转换涉及舍入。例如,如果您使用IEEE四倍精度,这些情况会更少见,但仍会发生。

您可以使用十进制库或任意精度库,但如果必须进行数万亿次计算,您可能不愿意在运行时支付使用它们的费用。

在这种情况下,你必须问自己一个问题,“我确实知道这些数字的准确程度如何?”然后你可以考虑,“0.135-0.027 <= 0.108是否可以允许被认为是真的吗?“在大多数情况下,这些问题的答案是”不准确“和”是“,你的问题就解决了。你可能会对这个解决方案感到不舒服,但它是摆动和环形交叉:错误 将“双向”发生(从某种意义上说,有时比较会在成功时失败,并且有时它会在失败时成功。)

如果单向失败是完全正常的,但是以其他方式失败绝对不是,您可以更改硬件的舍入模式(以适应您想要的偏差),或者您可以添加/减去ULP(以适应你想要的偏见。)

例如,请考虑以下内容(抱歉 C ,但我确信您明白了这一点):

double add_ulp(double x) {
    union {
        double x;
        unsigned sign : 1;
        unsigned expo : 11;
        unsigned long mant : 52;
    } inc;
    inc.x = x;

    inc.mant = 0;
    if (inc.expo >= 52 ) {
        inc.expo -= 52;
        return x+inc.x;
    }
    return x;
}

你可以这样使用:

if( x-y <= add_ulp(z) ) {
    // ...
}

它会在你的案例中为你提供的答案,但它会对你的结果产生偏见。如果这是你想要的偏见,那就不是问题,但如果不是,那就比你现在的问题更糟

希望这有帮助。

答案 1 :(得分:-1)

这可能会有所帮助: https://pythonhosted.org/bigfloat/

您也可以使用此控制精度。