识别二次方程中的误差

时间:2013-09-17 19:55:11

标签: python numerical-methods quadratic

假设您编写了一个Python程序来计算ax 2 + bx + c = 0的实根,其中给出了系数a,b和c,实数。这两种解决方案的传统公式是

x1 = (-b - sqrt(b*b-4*a*c)) / 2a, 
x2 = (-b + sqrt(b*b-4*a*c)) / 2a.

我需要识别公式没有意义的情况(系数的值)或导致大的舍入误差,并提出可以在这些情况下使用的替代公式,以避免出现问题。

我需要做什么?

1 个答案:

答案 0 :(得分:2)

有两种情况会出现问题。第一个是当平方根内的术语(“判别式”)变为负数时,即

if(b*b - 4*a*c < 0 ):
  # do something. This doesn't have real roots

第二个更微妙。当您减去两个大小几乎相同的大数字时,可能会出现舍入错误。 4*a*c << b*b时,较小的根将发生这种情况。你可以做一系列扩展:

b - sqrt(b*b - 4*a*c)
= b * ( 1 - sqrt(1 - 4 * a * c / (b * b)))
~ b * ( 1 - 1 + 2 * a * c / (b * b))        # when 4*a*c << b*b

这个词变为

2 * a * c / b

所以最终的根将是

x1 = - c / b

这是一个有趣的结果。当然另一个根仍然是

x2 = (b + sqrt( b * b - 4 * a * c)) / (2 * a)

那里的错误传播不多 - 虽然你可以说它会倾向于

x2 = - b / a

当c变得很小时。

所有这些与Python无关 - 这是基本的数学。我可能犯了错误 - 继续看看你是否能找到它们。

如需更多帮助,您可以查看http://en.wikipedia.org/wiki/Quadratic_equation#Floating-point_implementation

在数值稳定性方面提供了对这个问题的处理。除其他外,你会发现上面推导出的方程I(重新)称为“维塔公式”。