一尘不染

通过代码求解联立方程

algorithm

这似乎是一个令人难以置信的简单而愚蠢的问题,但是我发现的所有问题都让我难以理解。

我有两个非常基本的联立方程:

X = 2x + 2z
Y = z - x

既然我既知道X又知道Y,那么我将如何查找x和z?手工完成非常容易,但是我不知道如何在代码中完成。


阅读 315

收藏
2020-07-28

共1个答案

一尘不染

这似乎是一个非常简单而愚蠢的问题

一点也不。这是一个很好的问题,不幸的是它有一个复杂的答案。让我们解决

a * x + b * y = u
c * x + d * y = v

我在这里坚持2x2的情况。更复杂的情况将要求您使用库。

首先要注意的是Cramer公式不好用。计算行列式时

a * d - b * c

一旦您拥有了a * d ~ b * c,那么您将遭受灾难性的取消。这种情况很典型,您
必须 警惕。

简单性/稳定性之间的最佳权衡是部分枢纽。假设`|a|

|c|`。那么系统相当于

a * c/a * x + bc/a * y = uc/a
      c * x +    d * y = v

这是

cx + bc/a * y = uc/a
cx +       dy = v

现在,将第一个收益减去第二个收益

cx +       bc/a * y = uc/a
     (d - bc/a) * y = v - uc/a

现在可以直接解决:y = (v - uc/a) / (d - bc/a)x = (uc/a - bc/a * y) / c。计算d - bc/a比稳定ad - bc,因为我们除以最大数(不是很明显,但是它成立了-用非常接近的系数进行计算,您会明白为什么会这样)。

现在,如果为|c| > |a|,则只需交换行并以类似方式进行。

在代码中(请检查Python语法):

def solve(a, b, c, d, u, v):
    if abs(a) > abs(c):
         f = u * c / a
         g = b * c / a
         y = (v - f) / (d - g)
         return ((f - g * y) / c, y)
    else
         f = v * a / c
         g = d * a / c
         x = (u - f) / (b - g)
         return (x, (f - g * x) / a)

您可以使用完全旋转(需要交换x和y,以便始终以最大的系数进行第一除法),但这写起来比较麻烦,而且对于2x2的情况几乎不需要。

对于nxn情况,所有关键数据都封装在LU分解中,为此您应该使用一个库。

2020-07-28