python十进制()极其精确的表演时髦

时间:2017-07-06 18:48:23

标签: python

我正在尝试评估一个相当长而复杂的数学表达式,并从python十进制包中得到一些非常奇怪的结果。 (我已经尝试过使用常规花车而且它们没有足够的精度)。这是代码(它有点长,抱歉):

fal_media

以下是我得到的输出:

from decimal import *

def docalc (xi0,yi0,xi1,yi1,xi2,yi2,xi3,yi3,xo0,yo0,xo1,yo1,xo2,yo2,xo3,yo3):
    res = (((xi2 * (-yi0 + yi1) + xi1 * (yi0 - yi2) + xi0 * (-yi1 + yi2)) *
          ((xi2 * (-xo0 + xo1) * yi0 * yi1 + xi1 * (xo0 - xo2) * yi0 * yi2 +
            xi0 * (-xo1 + xo2) * yi1 * yi2) *
           (xi2 * xi3 * (xo2 - xo3) * yi0 + xi0 * xi3 * (-xo0 + xo3) * yi2 +
            xi0 * xi2 * (xo0 - xo2) * yi3) -
           (xi1 * xi2 * (-xo1 + xo2) * yi0 + xi0 * xi2 * (xo0 - xo2) * yi1 +
            xi0 * xi1 * (-xo0 + xo1) * yi2) *
           (xi3 * (xo0 - xo2) * yi0 * yi2 + xi2 * (-xo0 + xo3) * yi0 * yi3 +
            xi0 * (xo2 - xo3) * yi2 * yi3)) *
          (xi1 * xi2 * (yi0 - yi3) * (yo1 - yo2) +
           xi0 * (xi1 * (yi2 - yi3) * (yo0 - yo1) - xi2 * (yi1 - yi3) * (yo0 - yo2) +
                  xi3 * (yi1 - yi2) * (yo0 - yo3)) - xi1 * xi3 * (yi0 - yi2) * (yo1 - yo3) +
           xi2 * xi3 * (yi0 - yi1) * (yo2 - yo3)) +
          (-(xi2 * yi0) + xi0 * yi2) * (xi2 * xi3 * (xo2 - xo3) * (yi0 - yi1) +
                                        xi0 * xi3 * (xo0 - xo3) * (yi1 - yi2) +
                                        xi1 * (-(xi3 * (xo1 - xo3) * (yi0 - yi2)) + xi2 * (xo1 - xo2) * (yi0 - yi3) +
                                               xi0 * (xo0 - xo1) * (yi2 - yi3)) - xi0 * xi2 * (xo0 - xo2) * (
                                        yi1 - yi3)) *
          ((-(xi2 * (-xo0 + xo1) * yi0 * yi1) - xi1 * (xo0 - xo2) * yi0 * yi2 -
            xi0 * (-xo1 + xo2) * yi1 * yi2) *
           (xi1 * xi2 * (yi0 - yi3) * (yo1 - yo2) +
            xi0 * (xi1 * (yi2 - yi3) * (yo0 - yo1) - xi2 * (yi1 - yi3) * (yo0 - yo2) +
                   xi3 * (yi1 - yi2) * (yo0 - yo3)) -
            xi1 * xi3 * (yi0 - yi2) * (yo1 - yo3) + xi2 * xi3 * (yi0 - yi1) * (yo2 - yo3))
           - (xi1 * xi2 * (-xo1 + xo2) * yi0 + xi0 * xi2 * (xo0 - xo2) * yi1 +
              xi0 * xi1 * (-xo0 + xo1) * yi2) *
           (xi1 * yi0 * yi2 * yo0 - xi1 * yi0 * yi3 * yo0 + xi3 * yi0 * yi1 * (yo0 - yo1) -
            xi0 * yi1 * yi2 * yo1 + xi0 * yi1 * yi3 * yo1 + xi3 * yi1 * yi2 * (yo1 - yo2) -
            xi1 * yi0 * yi2 * yo2 + xi0 * yi1 * yi2 * yo2 - xi0 * yi2 * yi3 * yo2 +
            xi1 * yi2 * yi3 * yo2 + xi3 * yi0 * yi2 * (-yo0 + yo2) +
            xi2 * yi0 * (yi1 * (-yo0 + yo1) + yi3 * (yo0 - yo3)) + xi1 * yi0 * yi3 * yo3 -
            xi0 * yi1 * yi3 * yo3 + xi0 * yi2 * yi3 * yo3 - xi1 * yi2 * yi3 * yo3 +
            xi2 * yi1 * yi3 * (-yo1 + yo3)))))

    return (res);


def test():

    xi0 = 1.1;      yi0 = 1.1;      xi1 = 2.1;      yi1 = 1.1;      xi2 = 2.1;      yi2 = 2.1;      xi3 = 1.1;      yi3 = 2.1
    xo0 = 91.23;    yo0 = 82.34;    xo1 = 73.45;    yo1 = 64.56;    xo2 = 55.67;    yo2 = 46.78;    xo3 = 37.89;    yo3 = 28.90
    c_float = docalc(xi0, yi0, xi1, yi1, xi2, yi2, xi3, yi3, xo0, yo0, xo1, yo1, xo2, yo2, xo3, yo3)

    getcontext().prec = 19
    xi0d = Decimal(xi0);   yi0d = Decimal(yi0);    xi1d = Decimal(xi1);   yi1d = Decimal(yi1);    xi2d = Decimal(xi2);   yi2d = Decimal(yi2);    xi3d = Decimal(xi3);   yi3d = Decimal(yi3);
    xo0d = Decimal(xo0);   yo0d = Decimal(yo0);    xo1d = Decimal(xo1);   yo1d = Decimal(yo1);    xo2d = Decimal(xo2);   yo2d = Decimal(yo2);    xo3d = Decimal(xo3);   yo3d = Decimal(yo3);
    c_decimal_19 = docalc(xi0d, yi0d, xi1d, yi1d, xi2d, yi2d, xi3d, yi3d, xo0d, yo0d, xo1d, yo1d, xo2d, yo2d, xo3d, yo3d)

    getcontext().prec = 500
    xi0d = Decimal(xi0);   yi0d = Decimal(yi0);    xi1d = Decimal(xi1);   yi1d = Decimal(yi1);    xi2d = Decimal(xi2);   yi2d = Decimal(yi2);    xi3d = Decimal(xi3);   yi3d = Decimal(yi3);
    xo0d = Decimal(xo0);   yo0d = Decimal(yo0);    xo1d = Decimal(xo1);   yo1d = Decimal(yo1);    xo2d = Decimal(xo2);   yo2d = Decimal(yo2);    xo3d = Decimal(xo3);   yo3d = Decimal(yo3);
    c_decimal_500 = docalc(xi0d, yi0d, xi1d, yi1d, xi2d, yi2d, xi3d, yi3d, xo0d, yo0d, xo1d, yo1d, xo2d, yo2d, xo3d, yo3d)

    print("using floats: ",c_float);
    print("using Decimals() w/ prec=19: ",c_decimal_19);
    print("using Decimals() w/ prec=500: ",c_decimal_500);

test();

为了记录,Mathematica说实际答案是7.80201 * 10 ^ -11。使用具有如此长的复杂表达式的浮点数会导致可怕的舍入错误,我并不感到惊讶,但我很困惑,Decimal()类型(即使精度设置为500)也会返回奇怪的虚假结果。实际上,将精度从19提高到500似乎会导致结果变得更糟。有任何想法吗?这是python小数组包中的错误,或者是python中的一个错误,通常是非常冗长,复杂的数学表达式?感谢。

0 个答案:

没有答案