2012-08-11 105 views
1

二次方程的實根我試圖解決這個問題:計算以帕斯卡

(寫一個程序來計算二次方程式(AX + BX + C = 0)的實根。 -/2A

X2 =(-b - SQRT(b

X1 =(4AC)-b + SQRT(b ):根可使用以下公式計算 - 4AC))/ 2A

我寫了下面的代碼,但其不正確:

program week7_lab2_a1; 
var a,b,c,i:integer; 
x,x1,x2:real; 

begin 
    write('Enter the value of a :'); 
    readln(a); 

    write('Enter the value of b :'); 
    readln(b); 

    write('Enter the value of c :'); 
    readln(c); 

    if (sqr(b)-4*a*c)>=0 then 
    begin 
     if ((a>0) and (b>0)) then 
     begin 
      x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a; 
      x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a; 

      writeln('x1=',x1:0:2); 
      writeln('x2=',x2:0:2); 
     end 
     else 
     if ((a=0) and (b=0)) then 
      write('The is no solution') 
     else 
      if ((a=0) and (b<>0)) then 
      begin 
       x:=-1*c/b; 
       write('The only root :',x:0:2); 
      end; 
    end 
    else 
    if (sqr(b)-4*a*c)<0 then 
     write('The is no real root'); 

    readln; 
end. 

你知道爲什麼嗎?

並取a = -6,b = 7,c = 8 ..你可以在寫好pesudocode後進行檢查嗎?

回答

2

你有一個運算符優先級錯誤的位置:

x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a; 
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a; 

看到年底,2 * a沒有做什麼,你認爲它。它將表達式除以2,但由於優先規則,因此乘以a。這是你想要什麼:

x1:=(-1*b+sqrt(sqr(b)-4*a*c))/(2*a); 
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/(2*a); 

其實,這是因爲表達式的值左到右WRT括號,乘法和除法have the same priority。所以基本上,一旦它除以2,它就會說:「我已經完成了分工,我會按照所告訴的,將現在的數量乘以a」。

因爲它並沒有真正似乎從你給出的公式清楚,這是二次公式:

enter image description here

正如你所看到的,你需要通過2A來劃分,所以你必須使用括號這裏使它正常工作,就像這個方程的正確純​​文本表達式是x =( - b + - sqrt(b^2 - 4ac))/(2a)。


否則代碼看起來不錯,如果有些卷積(例如,可以丟棄的情況下(α= 0)和(b = 0)輸入之後,這將位以後簡化邏輯) 。你是否真的想排除負數係數,或者只是零係數?你應該檢查一下。

另外要小心浮點相等比較 - 它可以很好地處理0,但通常不適用於大多數常量,因此如果需要檢查一個值是否與另一個值相等,請使用epsilon(如下所示: abs(a - b) < 1e-6

+0

感謝Tomas。我想排除(sqr(b)-4 * a * c)的負值。但是,即使在將2 * a修改爲(2a)後,當我試圖通過應用a = -6,b = 7,c = 8來運行程序時,也沒有輸出。你能檢查它嗎?再次感謝 – user1592356 2012-08-11 16:01:43

+0

@ user1592356那部分是好的,我的意思是係數a,b,c。如果仔細查看代碼並瀏覽它,則會發現它完全忽略了「a」的負值。 – Thomas 2012-08-11 16:03:36

1

完全同意托馬斯在回答中所說的話。只想補充一些優化標誌:

您檢查判別值if語句,然後再次使用它:

if (sqr(b)-4*a*c)>=0 then 
... 
x1:=(-1*b+sqrt(sqr(b)-4*a*c))/2*a; 
x2:=(-1*b-sqrt(sqr(b)-4*a*c))/2*a; 

這不是很有效的 - 而不是一次你計算它評估判別值多次。你應該先計算判別值,並將其存儲到一些變量:

D := sqr(b)-4*a*c; 

之後,你可以在所有表​​達式中使用的評估值,就像這樣:

if (D >= 0) then 
... 
x1:=(-b+sqrt(D)/(2*a); 
x2:=(-b-sqrt(D)/(2*a); 

等。


而且,我不會寫-1*b ......取而代之的是隻使用在最壞的情況下-b0-b,而不是乘法。這裏乘法是不需要的。


編輯

還要說明一點:

您的代碼:

if (sqr(b)-4*a*c)>=0 then 
begin 
... 
end 
    else 
    if (sqr(b)-4*a*c)<0 then 
     write('The is no real root'); 

您在這裏仔細檢查,如果條件。我簡化此:

if (a) then 
    begin ... end 
else 
    if (not a) 
    ... 

如果您檢查not a(在你的代碼就相當於(sqr(b)-4*a*c)<0 - 在這種情況下,條件只能是假的(一),並沒有必要仔細檢查它。你應該把它扔掉。

+0

@ user1592356歡迎您,但我沒有提到係數:)。好吧,關於他們。你不應該檢查它們的值(只有在你的任務中這麼說)。相反,這裏只有3種情況:當D> 0時 - 當D = 0時,有2個不同的實根,只有一個實根(或2個相似的根),當D <0時,任何真正的根源。這就是所有,你不需要檢查任何係數,但只是判別式。 – Prizoff 2012-08-11 18:38:53