2012-08-11 77 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