-1

假设您编写了一个 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.

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

我需要做什么?

4

1 回答 1

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

它从数值稳定性的角度来解决这个问题。您会发现,我在上面(重新)推导出的方程式被称为“维埃塔公式”。

于 2013-09-17T20:09:30.773 回答