]]> ]]>

Квадратное уравнение

Квадратное уравнение — это уравнение вида Ax2 + Bx + C = 0, где A, B и C — заданные константы (с ограничением A != 0).

Первым шагом решения уравнения является вычисление дискриминанта D = B2-4AC. Если D = 0, уравнение имеет единственный действительный корень x = -B/2A, в противном случае существует пара корней x1 = (-B+sqrt(D))/2A, x2 = (-B-sqrt(D))/2A (корни являются действительными или комплексными в зависимости от знака дискриминанта).

Задача состоит в том, чтобы прочитать целочисленные константы A, B и C, заданные пользователем, вычислить корни уравнения и вывести их. Если A = 0, выведите сообщение об ошибке “Уравнение не является квадратным”. Корни следует выводить в формате a + ib, где a и b — дробные числа с 6 или менее знаками после десятичной запятой.

Этот класс примеров демонстрирует работу с дробными и комплексными числами (если язык предоставляет эти типы данных). Кроме того, для общения с пользователем может использоваться как консоль, так и графический интерфейс.

Пример для версий Borland C++ Builder 6

В этом примере используется класс complex<>, входящий в состав библиотеки STL. Все вычисления выполняются в комплексных числах, т.к. это позволяет не беспокоиться о знаке дискриминанта и различных представлениях корней для действительного и комплексного случаев.

Оператор >> класса complex<> перегружен так, что он распознает несколько форматов вводимых чисел, в т.ч. и числа без мнимой части, так что константы A, B и C читаются не как целые числа, а сразу как комплексные. Такая реализация позволяет расширить область применения примера до уравнений с дробными и даже комплексными коэффициентами.

Оператор << класса complex<> также перегружен и выводит любое комплексное число x как (x.real(),x.imag()), поэтому для вывода корней без мнимой части как обычных дробных чисел используется функция print.

#include <iostream>
#include <complex>
#include <math>

using namespace std;

void print(int ind, complex<double> x)
{   cout << "x" << ind << " = ";
    if (fabs(x.imag()) < 1E-6)
        cout << x.real() << endl;
    else cout << x << endl;
}

void main()
{   complex<double> A, B, C, D, x1, x2;
    cout << "A = ";
    cin >> A;
    if (abs(A)<1E-3)
    {   cout << "Not a quadratic equation." << endl;
        return;
    }
    cout << "B = ";
    cin >> B;
    cout << "C = ";
    cin >> C;

    A *= 2;
    D = B*B-A*C*2.0;
    if (abs(D)<1E-3)
        cout << "x = " << (-B/A).real();
    else
    {   print(1, (-B+sqrt(D))/A);
        print(2, (-B-sqrt(D))/A);
    }
}

Пример для версий SpiderMonkey (Firefox 3.5)

Пример выполняется в веб-браузере. Чтобы запустить пример, скопируйте код в файл quadratic.js и создайте файл HTML, находящийся в том же каталоге, содержащий следующий текст:

<head> <script type="text/javascript" src="1.js"></script> </head> <body> <form name="quadratic"> <input type="number" required="required" name="A"> <input type="number" required="required" name="B"> <input type="number" required="required" name="C"> <input type="button" value="Solve" onClick="solve()"> </form> <p id="output"> </p> </body>

Это создаст веб-страницу с тремя полями ввода и кнопкой. При нажатии на кнопку будет решено уравнение с введенными коэффициентами, и корни будут напечатаны под полями ввода.

В JavaScript нет типа данных для работы с комплексными числами, поэтому вычисления производятся в дробных числах и выполняется отдельная проверка на знак дискриминанта. Реализация позволяет решать квадратные уравнения не только с целыми, но и с дробными коэффициентами.

function print(real, imag) 
{   if (Math.abs(imag)<1E-6)
        return real;
    else
        return '('+real+','+imag+')';
}

function solve() 
{   A = document.quadratic.A.value;
    if (Math.abs(A)<1E-3)
    {   document.getElementById('output').innerHTML = 'Not a quadratic equation.';
        return;
    }
    B = document.quadratic.B.value;
    C = document.quadratic.C.value;
    A = 2*A;
    D = B*B-2*A*C;
    if (Math.abs(D)<1E-3)
    {   document.getElementById('output').innerHTML = 'x = '+(-B/A);
        return;
    }
    if (D>0)
        document.getElementById('output').innerHTML = 'x1 = '+print((-B+Math.sqrt(D))/A, 0)+'<br />x2 = '+print((-B-Math.sqrt(D))/A, 0);
    else
        document.getElementById('output').innerHTML = 'x1 = '+print(-B/A,Math.sqrt(-D)/A)+'<br />x2 = '+print(-B/A,-Math.sqrt(-D)/A);
}

Пример для версий gcj 3.4.5 Sun Java 6

В Java нет типа данных для работы с комплексными числами, поэтому вычисления производятся в дробных числах и выполняется отдельная проверка на знак дискриминанта. Реализация позволяет решать квадратные уравнения не только с целыми, но и с дробными коэффициентами.

Коэффициенты читаются из потока System.in. Напрямую из него можно читать только отдельные байты, поэтому для повышения комфортности чтения используются классы InputStreamReader и BufferedReader. Строки, прочитанные из System.in, преобразуются в числа типа double с помощью метода Double.parseDouble(). Все операции ввода в Java должны находиться внутри блоков try ... catch, чтобы гарантированно обрабатывать IOException — класс исключений, порождаемых функциями чтения.

import java.util.*;
import java.io.*;

public class Quadratic {
    static String print(double real, double imag)
    {   if (Math.abs(imag)<1E-6)
            return ""+real;
        else 
            return "("+real+","+imag+")";
    }
    public static void main(String[] args)
    {   double A,B,C,D;
      try {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("A = ");
        A = Double.parseDouble(br.readLine());
        if (Math.abs(A)<1E-3)
        {   System.out.println("Not a quadratic equation.");
            return;
        }
        System.out.print("B = ");
        B = Double.parseDouble(br.readLine());
        System.out.print("C = ");
        C = Double.parseDouble(br.readLine());
      }
      catch (Exception e) {
        System.err.println("An error occured while reading input parameters.");
        return;
      }
        A = 2*A;
        D = B*B-2*A*C;
        if (Math.abs(D)<1E-3)
        {   System.out.println("x = "+(-B/A));
            return;
        }
        if (D>0)
            System.out.println("x1 = "+print((-B+Math.sqrt(D))/A, 0)+"\nx2 = "+print((-B-Math.sqrt(D))/A, 0));
        else
            System.out.println("x1 = "+print(-B/A,Math.sqrt(-D)/A)+"\nx2 = "+print(-B/A,-Math.sqrt(-D)/A));
    }
}

Пример для версий Oracle 10g SQL

Этот пример тестировался в SQL*Plus и TOAD.

Чистый SQL позволяет вводить переменные в процессе исполнения запроса в виде заменяемых переменных. Для определения такой переменной ее имя (в данном случае A, B и C) следует использовать с амперсандом & перед ним каждый раз, когда нужно сослаться на эту переменную. Когда запрос выполняется, пользователь получает запрос на ввод значений всех заменяемых переменных, использованных в запросе. После ввода значений каждая ссылка на такую переменную заменяется на ее значение, и полученный запрос выполняется.

Существует несколько способов ввести значения для заменяемых переменных. В данном примере первая ссылка на каждую переменную предваряется не одинарным, а двойным амперсандом &&. Таким образом значение для каждой переменной вводится только один раз, а все последующие ссылки на нее будут заменены тем же самым значением (при использовании одиночного амперсанда в SQL*Plus значение для каждой ссылки на одну и ту же переменную приходится вводить отдельно). Следует отметить, что ссылки заменяются на значения “как есть”, поэтому отрицательные коэффициенты следует вводить в скобках.

Первая строка примера задает символ для десятичного разделителя, который используется при преобразовании чисел-корней в строки.

Сам запрос состоит из четырех разных запросов. Каждый запрос возвращает строку, содержащую результат вычислений, в одном из случаев (A=0, D=0, D>0 и D<0) и ничего — в трех остальных случаях. Результаты всех четырех запросов объединяются, чтобы получить окончательный результат.

alter session set NLS_NUMERIC_CHARACTERS='. ';

select 'Not a quadratic equation.' ans
  from dual
 where &&A = 0
union
select 'x = ' || to_char(-&&B/2/&A)
  from dual
 where &A != 0 and &B*&B-4*&A*&&C = 0
union
select 'x1 = ' || to_char((-&B+sqrt(&B*&B-4*&A*&C))/2/&A) || ', x2 = ' || to_char(-&B-sqrt(&B*&B-4*&A*&C))/2/&A
  from dual
 where &A != 0 and &B*&B-4*&A*&C > 0
union
select 'x1 = (' || to_char(-&B/2/&A) || ',' || to_char(sqrt(-&B*&B+4*&A*&C)/2/&A) || '), ' || 
       'x2 = (' || to_char(-&B/2/&A) || ',' || to_char(-sqrt(-&B*&B+4*&A*&C)/2/&A) || ')' 
  from dual
 where &A != 0 and &B*&B-4*&A*&C < 0;

Пример для версий UCBLogo 6.0

В этом примере определяется функция, принимающая в качестве аргументов коэффициенты квадратного уравнения и выводящая на печать его корни.

to quadratic :A :B :C
   if :A = 0 [(print [Not a quadratic equation.])
              stop
             ]
   make "D :B*:B - 4*:A*:C
   if :D = 0 [(print [x = ] -:B/2/:A)
              stop
             ]
   if :D > 0 [(print [x1 = ] (-:B+sqrt :D)/2/:A)
              (print [x2 = ] (-:B-sqrt :D)/2/:A)
              stop
             ]
   (print [x1 = (] -:B/2/:A [,] (sqrt (-:D))/2/A [)])
   (print [x2 = (] -:B/2/:A [,] (-sqrt (-:D))/2/A [)])
end

Пример для версий Corman Common Lisp 3.0 gcl 2.6.6

Common Lisp позволяет работать с комплексными числами и выводить их на печать в формате #C(real imag). Функция write-to-string преобразует число в строку.

(defun quadratic-roots-2 (A B C)
  (cond ((= A 0) (string "Not a quadratic equation."))
    (t
    (let ((D (- (* B B) (* 4 A C))))
      (cond ((= D 0) (concatenate 'string "x = " (write-to-string (/ (+ (- B) (sqrt D)) (* 2 A)))))
        (t
        (values (concatenate 'string "x1 = " (write-to-string (/ (+ (- B) (sqrt D)) (* 2 A))))
                (concatenate 'string "x2 = " (write-to-string (/ (- (- B) (sqrt D)) (* 2 A)))))))))))

Пример для версий gnat 3.4.5

Ada предоставляет тип данных для работы с комплексными числами, который требует использования пакетов Generic_Complex_Types и Generic_Complex_Elementary_Functions с предварительной инициализацией их типом данных для хранения комплексных чисел (в данном случае — Float). Ada не поддерживает неявные преобразования типов, поэтому все преобразования выполняются в явном виде.

with Ada.Text_IO, 
     Ada.Integer_Text_IO,
     Ada.Float_Text_IO,
     Ada.Numerics.Elementary_Functions,
     Ada.Text_IO.Complex_IO, 
     Ada.Numerics.Generic_Complex_Types,
     Ada.Numerics.Generic_Complex_Elementary_Functions;
use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Float_Text_IO;

procedure QuadraticEquation is
    package Complex_Types is new Ada.Numerics.Generic_Complex_Types (Float);
    package Complex_Functions is new Ada.Numerics.Generic_Complex_Elementary_Functions(Complex_Types);
    package Complex_IO is new Ada.Text_IO.Complex_IO (Complex_Types);

    use Complex_Types, Complex_IO;

    A,D: Integer;
    A2f, S: Float;
    Dc: Complex;
begin
    Put("A = ");
    Get(Item => A);
    if A = 0 then
        Put_Line("Not a quadratic equation.");
        return;
    end if;
    Put("B = ");
    Get(B);
    Put("C = ");
    Get(C);
    A2f := Float(2*A);
    Bf := Float(B);

    D := B*B-4*A*C;
    if D = 0 then
        Put("x = ");
        Put(-Bf/A2f);
    elsif D > 0 then
        S := Ada.Numerics.Elementary_Functions.Sqrt(Float(D));
        Put("x1 = ");
        Put((-Bf+S)/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-S)/A2f);
    else
        Dc := Compose_From_Cartesian (Re => Float(D), Im => 0.0);
        Put("x1 = ");
        Put((-Bf+Complex_Functions.Sqrt(Dc))/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-Complex_Functions.Sqrt(Dc))/A2f);
    end if;
end QuadraticEquation;

Пример для версий GHC 6.10.4

Haskell предоставляет тип данных для работы с комплексными числами. Функция quadratic принимает в качестве аргумента список трех комплексных чисел (коэффициентов уравнения) и возвращает список корней уравнения. Запись вида root sign позволяет передать знак операции в качестве аргумента и таким образом обобщить запись двух знаков при квадратном корне из дискриминанта.

module Main where

import Data.Complex
import System.IO (hFlush, stdout)

quadratic :: (Complex Double, Complex Double, Complex Double) -> [Complex Double]
quadratic (0, _, _) = []
quadratic (a, b, c)
      | d == 0 = [root (+)]
      | otherwise = [root (+), root (-)]
  where d = b*b - 4*a*c
        root sign = sign (-b) (sqrt d) / (2*a)

main = do
    putStr "A = "
    hFlush stdout
    a <- readLn :: IO Double
    putStr "B = "
    hFlush stdout
    b <- readLn :: IO Double
    putStr "C = "
    hFlush stdout
    c <- readLn :: IO Double
    print $ quadratic (realToFrac a, realToFrac b, realToFrac c)

Пример для версий Visual Prolog 7.2

Для запуска создайте новый проект с UI Strategy “Console” и замените содержимое файлов main.cl и main.pro приведенным кодом.

В main.cl добавлена одна строка q : () procedure().. Ключевое слово procedure описывает поведение предиката, указывая, что его вычисление всегда будет успешным и будет найдено ровно одно решение, так что откаты не понадобятся.

В main.pro находится собственно определение нового предиката. Предикат q не принимает аргументов, поскольку читает необходимые данные из stdio. Условное оценивание (конструкцияif-then-else) работает точно так же, как в других языках. Единственным отличием является знак отсечения ! перед then. Это означает, что как только условие if выполняется, откат уже не потребуется.

Хитрость этого примера в том, что невозможно сразу вычислить дискриминант, как в других языках. Тип данных по умолчанию для переменной D в присвоении D = B*B-4*A*C -uReal, который может хранить только неотрицательные числа.

% main.cl
class main
    open core

predicates
    classInfo : core::classInfo.
    q : () procedure().
predicates
    run : core::runnable.

end class main

% main.pro
implement main
    open core

constants
    className = "main".
    classVersion = "".

clauses
    classInfo(className, classVersion).
    q() :-
        stdio::write("A = "), 
        A = stdio::read(),
        if (A = 0), ! then
            stdio::write("Not a quadratic equation."), stdio::nl
        else
            stdio::write("B = "), 
            B = stdio::read(),
            stdio::write("C = "), 
            C = stdio::read(),
            if (B*B = 4*A*C), ! then
                stdio::writef("x = %f", -B/2.0/A)
            elseif (B*B > 4*A*C), ! then
                D = B*B-4*A*C,
                stdio::writef("x1 = %f\n", (-B+math::sqrt(D))/2.0/A),
                stdio::writef("x2 = %f", (-B-math::sqrt(D))/2.0/A)
            else
                D = -B*B+4*A*C,
                stdio::writef("x1 = (%f, %f)\n", -B/2.0/A, math::sqrt(D)/2.0/A),
                stdio::writef("x2 = (%f, %f)", -B/2.0/A, -math::sqrt(D)/2.0/A)
            end if
        end if.
        
clauses
    run():-
        console::init(),
        q(),
        succeed().
end implement main

goal
    mainExe::run(main::run).

Пример для версий gpc 20070904 Turbo Pascal 1.0 Turbo Pascal 2.0 Turbo Pascal 3.0 Turbo Pascal 4.0 Turbo Pascal 5.0 Turbo Pascal 6.0

В Pascal нет встроенного комплексного типа данных, поэтому вычисления проводятся в типе real. Библиотечная функция halt позволяет выйти из текущего блока (в более поздних версиях заменена на exit).

program Quadratic;

var
   A,B,C,D: integer;

begin
   write('A = ');
   readln(A);
   if (A=0) then
   begin
      writeln('Not a quadratic equation.');
      halt;
   end;
   write('B = ');
   readln(B);
   write('C = ');
   readln(C);
   D := B*B-4*A*C;
   if (D=0) then
   begin
      writeln('x = ',-B/2.0/A);
      halt;
   end;
   if (D>0) then
   begin
      writeln('x1 = ',(-B+Sqrt(D))/2.0/A);
      writeln('x2 = ',(-B-Sqrt(D))/2.0/A);
   end
   else
   begin
      writeln('x1 = (',-B/2.0/A,',',Sqrt(-D)/2.0/A,')');
      writeln('x2 = (',-B/2.0/A,',',-Sqrt(-D)/2.0/A,')');
   end;
end.

Пример для версий QuickBasic 4.50

PRINT "A = "
INPUT A
IF (A = 0) THEN
    PRINT "Not a quadratic equation."
ELSE
    PRINT "B = "
    INPUT B
    PRINT "C = "
    INPUT C
    D = B * B - 4 * A * C
    IF (D = 0) THEN
        PRINT "x = " + STR$(-B / 2! / A)
    ELSE
        IF (D > 0) THEN
            PRINT "x1 = " + STR$((-B + SQR(D)) / 2! / A)
            PRINT "x2 = " + STR$((-B - SQR(D)) / 2! / A)
        ELSE
            PRINT "x1 = (" + STR$(-B / 2! / A) + "," + STR$(SQR(-D) / 2! / A) + ")"
            PRINT "x2 = (" + STR$(-B / 2! / A) + "," + STR$(-SQR(-D) / 2! / A) + ")"
        END IF
    END IF
END IF

Пример для версий Wolfram Mathematica 7.0.1.0

после ввода значений определяем переменную y-решаемое квадратное уравнение. Так как x не определено, в уравнении оно останется обычной переменной (например, если написать Print[y], мы увидим уравнение c + b x + a x^2, где a,b и c-введенные числа). Функция Reduce вычисляет значиния переменных, при котором указанное условие будет истинным. Условие в данном случае-квадратное уравнение, а переменная-x.

a = Input["Input a", 0]
b = Input["Input b", 0]
c = Input["Input c", 0]
y = a*x^2 + b*x + c;
Print[Reduce[y == 0]]

Пример для версий Euphoria 3.1.1

include get.e

atom A
atom B, C
atom D

A = prompt_number("A=", {})
if A = 0 then
    puts(1,"Not a quadratic equation.\n")
else
    B = prompt_number("B=", {})
    C = prompt_number("C=", {})
    D = B*B - 4*A*C
    if D = 0 then
        printf(1,"x = %g\n", -B/2/A)
    else
        if D > 0 then
            printf(1,"x1 = %g\n", -B+sqrt(D)/2/A)
            printf(1,"x2 = %g\n", -B-sqrt(D)/2/A)
        else
            printf(1,"x1 = (%g,%g)\n", {-B/2/A, sqrt(-D)/2/A})
            printf(1,"x2 = (%g,%g)\n", {-B/2/A, sqrt(-D)/2/A})
        end if
    end if
end if
В закладки: ]]> Пиктограмма del.icio.us Пиктограмма БобрДобр.ru Пиктограмма Memori.ru Пиктограмма МоёМесто.ru ]]>