1

私はこの問題を解決しようとしています:

(2次方程式の実根を計算するプログラムを作成します(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-6) 。

于 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...代わりに、-bまたは0-b最悪の場合、乗算ではなく使用します。ここでの乗算は必要ありません。


編集

もう 1 つ注意:

あなたのコード:

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 の場合) false のみであり、再確認する必要はありません。あなたはそれを捨てるべきです。

于 2012-08-11T15:58:07.273 に答える