1

我正在尝试解决这个问题:

(编写一个程序来计算二次方程的实根(ax 2 + bx + c = 0)。根可以使用以下公式计算:

x1 = (-b + sqrt(b 2 - 4ac))/2a

x2 = (-b - sqrt(b 2 - 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 .. 你可以在编写伪代码后进行桌面检查吗?

4

2 回答 2

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);

事实上,这是因为表达式是从左到右求值的括号,并且乘法和除法具有相同的优先级。所以基本上,一旦它除以 2,它就会说“我已经完成了除法,我将a按照告诉的方式将我现在拥有的东西相乘”。

由于您给出的公式似乎并不清楚,因此这是二次公式:

在此处输入图像描述

如您所见,您需要除以 2a,因此您必须在此处使用方括号以使其正常工作,就像此等式的正确纯文本表达式是 x = (-b +- sqrt(b^2 - 4ac) ) / (2a)。


否则代码看起来很好,如果有些复杂(例如,您可以在输入后立即丢弃 (a = 0) 和 (b = 0) 的情况,这将稍后简化逻辑)。您真的是要排除负系数,还是仅仅排除零系数?你应该检查一下。

还要小心浮点相等比较 - 它适用于 0,但通常不适用于大多数常量,因此如果您需要检查一个值是否等于另一个值(例如:),请改用abs(a - b) < 1e-6epsilon

于 2012-08-11T15:01:52.223 回答
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 条件。我简化了这个:

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

您在哪里检查not a (在您的代码中它对应于(sqr(b)-4*a*c)<0 - 在这种情况下,条件只能为假(对于 a),无需仔细检查。你应该把它扔掉。

于 2012-08-11T15:58:07.273 回答