Вычислить действительные корни квадратного уравнения в Паскале

Я пытаюсь решить эту проблему:

(Напишите программу для вычисления действительных корней квадратного уравнения (ax2 + bx + c = 0). Корни можно вычислить, используя следующие формулы:

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

и

x2 = (-b - sqrt(b2 - 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... можете ли вы проверить это после написания псевдокода?


person Waleed    schedule 11.08.2012    source источник


Ответы (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) ) / (2а).


В противном случае код выглядит нормально, хотя и несколько запутан (например, вы можете отбросить случаи, когда (a = 0) и (b = 0) сразу после ввода, что немного упростит логику позже). Вы действительно хотели исключить отрицательные коэффициенты или просто нулевые коэффициенты? Вы должны проверить это.

Также будьте осторожны со сравнением равенства с плавающей запятой - оно отлично работает с 0, но обычно не работает с большинством констант, поэтому вместо этого используйте эпсилон, если вам нужно проверить, равно ли одно значение другому (например: abs(a - b) < 1e-6)

person Thomas    schedule 11.08.2012
comment
Спасибо, Томас. Я хотел исключить отрицательное значение (sqr(b)-4*a*c). Однако даже после изменения 2*a на (2a) не было вывода, когда я пытался запустить программу, применяя a=-6 , b=7 ,c=8. Можешь проверить, чувак. Спасибо еще раз - person Waleed; 11.08.2012
comment
@ user1592356 с этой частью все в порядке, я имел в виду коэффициенты a, b, c. Если вы внимательно посмотрите на свой код и пройдетесь по нему, вы заметите, что он полностью игнорирует отрицательные значения экземпляра a. - person Thomas; 11.08.2012

Полностью согласен с тем, что сказал Томас в своем ответе. Просто хочу добавить некоторые отметки оптимизации:

Вы проверяете значение дискриминанта в операторе 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 в худшем случае, но не умножение. Умножение здесь не нужно.


ИЗМЕНИТЬ:

Еще одно замечание:

Ваш код:

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) и перепроверять его не нужно. Вы должны просто выбросить его.

person Prizoff    schedule 11.08.2012
comment
@user1592356 user1592356 Пожалуйста, но я ничего не сказал о коэффициентах :). Хорошо, о них. Вы вообще не должны проверять их значения (только если это указано в вашем задании). Вместо этого у вас есть только и точные 3 ситуации здесь: когда D > 0 - у вас есть 2 разных действительных корня, когда D = 0 - у вас есть ровно один действительный корень (или 2 подобных корня), а когда D ‹ 0 - у вас нет любые настоящие корни. Вот и все, и вам не нужно проверять никакие коэффициенты, а только дискриминант. - person Prizoff; 11.08.2012