6.8 这个实现,有点问题。

来源:6-8 实现更一般化的高斯-约旦消元法

jandy_chen

2020-03-17

如题针对:

A9 = Matrix([[2,0,1],
             [-1,-1,-2],
             [-3,0,1]])
b9 = Vector([1, 0, 0])
ls9 = LinearSystem(A9, b9)
if not ls9.gauss_jordan_elimination():
    print("No Solution!")
ls9.fancy_print()
---------
会得出这样得结果:
No Solution!

1.0 0.0 0.0 | 0.19999999999999996
0.0 0.0 1.0 | 0.6000000000000001
0.0 -1.0 0.0 | 1.4000000000000001

=====
经调试,发现判断主元时,没有考虑是负数情况,缺少变负为正考虑;
试着优化代码如下:
## 完成前向高斯消元

def _forward(self):
i,k =0,0
while i<self._m and k<self._n:
    if self.Ab[i][k] < 0:  ##增加判断
        self.Ab[i] = self.Ab[i]*(-1)

但是打印结果发现会对:0.0也有-号了
1.0 0.0 0.0 | 0.19999999999999996
-0.0 1.0 0.0 | -1.4000000000000001
0.0 0.0 1.0 | 0.6000000000000001

请问老师,针对这类情况,您会怎么优化,改进代码??

写回答

1回答

liuyubobobo

2020-03-19

赞!


这里确实有问题。我看了一下。其实在判断哪一个是主元行的时候,应该比较绝对值。可以这么修改:

def _max_row(self, index_i, index_j, n):
    best, ret = abs(self.Ab[index_i][index_j]), index_i
    for i in range(index_i + 1, n):
        if abs(self.Ab[i][index_j]) > best:
            best, ret = abs(self.Ab[i][index_j]), i
    return ret


当然,对于你的方法,对负数主元行做一下翻转,也是没问题的。


至于打印的结果,有 -0.0,是浮点误差的原因。换句话说,计算的结果,按照浮点数的方式解析,符号位是负的。使用计算机做浮点运算,浮点误差是不可避免的。如果你一定要避免,只能在打印输出的时候再做特殊判断,比如我们实现了 is_zero,我们可以在打印前,判断这个数 is_zero(x) 是否为 True,如果是 True,就统一打印 0,而不是将打印方式全盘交给 Python。


继续加油!:)

2
1
程序员班吉
def _max_row(self, index_i, index_j, n): 老师,我在看代码的时候发现_max_row函数的形参数量有点问题,在_forward函数调用的时候只传了两个参数i和n两个参数
2020-04-05
共1条回复

结合编程学数学 专为程序员设计的线性代数

创新设计,通俗易懂。编程结合数学,bobo带你彻底征服线性代数

3404 学习 · 375 问题

查看课程