2015-09-16 141 views
3
from math import sqrt 


a=1e-8 
b=10 
c=1e-8 

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

print 'x1 = {}'.format(x1) 
print 'x2 = {}'.format(x2) 

print (4*a*c) 
print (sqrt(b**2-4*a*c)) 
print b**2 
print 2*a 

更精確的十進制值當我運行程序,這將返回:我怎樣才能在Python

x1 = -1e+09 
x2 = 0.0 

4e-16 
10.0 
100.0 
2e-08 

我需要的是X2等於-1e-9。

的問題似乎是與

sqrt((b**2)-(4*a*c)) 

因爲它給出了10,結果,顯然是因爲4 *(10^-8)*(10^-8)幾乎等於0,和被python視爲0。

這導致:

sqrt((b**2)-(4*a*c)) = sqrt(b**2) = sqrt(10**2) = 10 

任何幫助,將不勝感激

回答

6

使用十進制模塊:

from decimal import Decimal 
a = Decimal('1E-8') 
b = 10 
c = Decimal('1E-8') 
x1 = ((-b)-((b**2)-(4*a*c)).sqrt())/(2*a) 
x2 = ((-b)+((b**2)-(4*a*c)).sqrt())/(2*a) 
print 'x1 = {}'.format(x1) 
print 'x2 = {}'.format(x2) 

結果

x1 = -999999999.999999999000000000 
x2 = -1.0000000000E-9 
0

您還可以使用該對於相同的庫,具有任意的精度。

from bigfloat import sub, add, mul, div, sqr, sqrt, precision 

a=1e-8 
b=10 
c=1e-8 
p = 100 

D = sub(sqr(b) , mul(4, mul(a,c)), precision(p)) 

x1 = div(- add(b , sqrt(D, precision(p))) , mul(2,a), precision(p)) 
x2 = div(- sub(b , sqrt(D, precision(p))) , mul(2,a), precision(p)) 

print x1,x2 

-999999999.99999997907743916987153 -9.9999999999981901320509082432747e-10 
5

你並不需要額外的精度來解決這個問題:Python的float s已具有足夠的精度工作。你只需要一個(稍微)更聰明的算法。

您的問題從兩個幾乎相等的計算值的減法莖:爲b正值且較大(相比於ac)當你做-b + sqrt(b*b-4*a*c),你最終有較大的相對誤差的結果。但請注意,此問題僅適用於兩個根中的一個:在-b - sqrt(b*b-4*a*c)中,沒有這樣的問題。同樣,對於b大的和負的,第一根很好,但第二根可能會失去準確性。

的解決方案是使用現有的公式來計算的根源取其沒有取消的問題,然後使用不同的配方爲其他根(基本上,使用的事實,你知道的產品兩根是c/a)。該公式是2c/(-b +/- sqrt(b*b-4*a*c))

下面是一些示例代碼。它採用math.copysign選擇那些不會導致取消錯誤標誌:

>>> from math import sqrt, copysign 
>>> def quadratic_roots(a, b, c): 
...  discriminant = b*b - 4*a*c 
...  q = -b - copysign(sqrt(discriminant), b) 
...  root1 = q/(2*a) 
...  root2 = (2*c)/q 
...  return root1, root2 
... 
>>> quadratic_roots(a=1e-8, b=10, c=1e-8) 
>>> (-1000000000.0, -1e-09) 

這本書以數值不穩定的最嚴重的可能原因。在判別式的計算中,如果b*b碰巧非常接近4*a*c,還有第二個可能的原因。在這種情況下,可能會丟失多達一半的正確有效數字(因此每個根只能得到7-8位準確的數字)。在這種情況下獲得全精度結果需要使用擴展精度來計算判別式。

loss of significance維基百科的文章正好包含這個問題的一個有用的討論。