二次求解器中的舍入误差

时间:2012-12-28 16:55:06

标签: python rounding equation solver quadratic

我是python的新手,我正在尝试编写一些代码来解决给定的二次函数。我在使用浮点数中的舍入错误时遇到了一些问题,我认为因为我将两个非常大的数字除以非常小的差异。 (此外我假设所有输入现在都有真正的解决方案。)我已经把两个不同版本的二次方程式来表示我的问题。它适用于大多数输入,但是当我尝试a = .001b = 1000c = .001时,我会得到两个有显着差异的答案。这是我的代码:

from math import sqrt

a = float(input("Enter a: "))
b = float(input("Enter b: "))
c = float(input("Enter c: "))

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

print("The solutions are: x = ",xn,", ",xp,sep = '')

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

print("The solutions are: x = ",xn,", ",xp,sep = '')

5 个答案:

答案 0 :(得分:1)

我不是数学领域的专家,但我相信你应该使用numpy(数学的py模块),由于计算机上的内部数字表示,你的微积分将不匹配真正的数学。 (浮点算术)

http://docs.python.org/2/tutorial/floatingpoint.html

检查这几乎是你想要的。

http://www.annigeri.in/2012/02/python-class-for-quadratic-equations.html

答案 1 :(得分:1)

要使用浮点数获得更精确的结果,请注意以减去相似的数量。对于二次x^2 + a x + b = 0,您知道根x1x2生成

b = x1 * x2

计算具有较大绝对值的那个,并从这个关系中获得另一个。

答案 2 :(得分:0)

解决方案:

用户dhunter建议的

Numpy 通常是python中数学的最佳解决方案。 numpy库能够在许多不同的领域进行快速准确的数学运算。

在Python 2.4中添加了

十进制数据类型如果您不想下载外部库并且不希望执行许多长或复杂的公式,则十进制数据类型可能符合要求。 只需添加:

from decimal import *

到你的代码的顶部,然后用单词Decimal替换单词float的所有实例(注意大写的“D”。)

Ex:Decimal(1.1047262519)而不是float(1.1047262519)

理论值:

浮点运算基于二进制数学运算,因此并不总是完全符合用户的期望。浮点数的优秀描述。小数类型位于Here

答案 3 :(得分:0)

您应该处理特殊情况:

  1. a == 0表示线性方程式和一个根:x = -c/b
  2. b == 0表示x1形式的两个根,x2 =±sqrt(-c / a)
  3. c == 0表示两个根,但其中一个为零:x*(ax+b) = 0
  4. 如果判别式为负,则有两个复共轭根。
  5. 我建议用这种方式计算判别式:

    discriminant = b*sqrt(1.0-4.0*a*c/b)
    

    我还建议你阅读:

    https://math.stackexchange.com/questions/187242/quadratic-equation-error

答案 4 :(得分:0)

前面提到的numpy模块与问题中提到的舍入错误并不特别相关。另一方面,decimal模块可以以强力方式使用以获得准确的计算。来自ipython解释器会话的以下片段说明了它的使用(默认为28位精度),并且还显示相应的浮点计算仅具有5位小数的精确度。

In [180]: from decimal import Decimal
In [181]: a=Decimal('0.001'); b=Decimal('1000'); c=Decimal('0.001')
In [182]: (b*b - 4*a*c).sqrt()
Out[182]: Decimal('999.9999999979999999999980000')
In [183]: b-(b*b - 4*a*c).sqrt()
Out[183]: Decimal('2.0000000000020000E-9')
In [184]: a = .001; b = 1000; c = .001
In [185]: math.sqrt(b*b - 4*a*c)
Out[185]: 999.999999998
In [186]: b-math.sqrt(b*b - 4*a*c)
Out[186]: 1.999978849198669e-09
In [187]: 2*a*c/b
Out[187]: 1.9999999999999997e-09
平方根的

Taylor series提供了一种在4acb**2相比较小时使用的替代方法。在这种情况下,√(b*b-4*a*c) ≈ b - 4*a*c/(2*b)b - √(b*b-4*a*c) ≈ 2*a*c/b。从上面的[187]项中可以看出,泰勒级数计算在使用浮点而不是十进制时给出了12位精确的结果。使用另一个泰勒系列术语可能会增加几个数字的准确性。