Трофим Роцкий
Редкая программа обходится без простейших алгебраических действий:
"плюс", "минус", "разделить", "умножить" - их delphi понимает и заботливо выделяет
синим цветом. Но позже начинаются трудности. Стоит вам прописать что-то вроде
edit1.text:= 'Координаты окна: ' + form1.left, + ', ' + form1.top,
как компилятор выдает сообщение: "incompatible types: string and
integer".
Что же это за типы и почему они несовместимы?
Информация может быть различной: текстовой, графической, цифровой, в десяти,-
восьми,- шестнадцатеричной и т.п. системах. Чтобы корректно воспринимать ее,
в delphi, да и во всех других языках, введены переменные, или типы (types).
В примере выше мы столкнулись с двумя из них, наиболее распространенными. string
- буквально "строка", текстовая информация. integer - простое число в
диапазоне -2147483648…2147483647. Хотя из ведра в сито перелить нельзя, добрый
borland предоставил нам функции для перевода из одного типа в другой (из модуля
sysutils.pas):
function inttostr(value: integer): string;
function strtoint(const s: string): integer;
Обратите внимание на возвращаемые значения функций. Наш пример должен выглядеть
так:
edit1.text:= 'Координаты окна: ' + inttostr(form1.left), + ', ' + inttostr(form1.top);
form1.top:=strtoint(edit2.text);
Посмотрите на вторую строчку кода. Значение edit2.text должно быть ТОЛЬКО числовым,
иначе вы получите сообщение об ошибке.
А если нужно работать с иррациональными числами, например, с числом "пи"?
Для таких данных существует свой тип: real. Переменной такого типа можно
присвоить значение параметра integer без всяких промежуточных функций,
но наоборот сделать нельзя. А чтобы увязать real с текстом, существуют
команды:
function floattostr(value: extended): string;
function strtofloat(const s: string): extended;
тоже из модуля sysutils.pas. (Поэтому не забывайте декларировать этот модуль
при создании консольного приложения с математическими действиями.) Пропишите
что-нибудь вроде
edit1.text:=floattostr(pi),
чтобы оценить возможности переменной real.
С её помощью можно уже производить более серьезные вычисления, например, возведение
в квадрат посредством функции sqr(x: real) и извлечение
квадратного корня: sqrt(x: real), что в модуле system.pas.
Там же можно найти функции sin и cos с аналогичными параметрами.
Там, где синус с косинусом, должен быть тангенс и какой-никакой секонс, которые
и присутствуют в виде функций tan, cotan, cosecant, sec, arcsin, arccos,
arccot, arcsec и прочая в модуле math.pas. Модуль этот незаменим
также, если вы хотите возвести число в степень.
function power(const base: extended; const exponent: extended):extended,
где base - число, которое возводиться в степень, exponent
- показатель степени.
form1.caption:=power(2,3); //возведение числа 2 в куб
Вот еще некоторые сокровища модуля math:
hypot - вычисление гипотенузы по длине катетов;
radtodeg, degtorad - преобразование радианов в градусы
и наоборот;
floor - округление в меньшую строну;
ceil - округление в большую сторону;
sincos - вычисление синуса и косинуса;
mean - среднее арифметическое в комбинации чисел. (Например:
caption:=floattostr(mean([10,10,2])) - находит среднее арифметическое
трех данных чисел, но, конечно же, искомых чисел может быть и больше, и
меньше указанных в примере трех.)
Часто бывает, что нужно прочертить прямую точно по центру image1, что невозможно
сделать делением параметра image1.width на два, поскольку в итоге почти всегда
получается иррациональное real-число.
Мы воспользуемся командой div, вычисляющей результат деления - целое число -
без остатка.
image1.canvas.moveto(image1.width div 2, 0);
image1.canvas.lineto(image1.width div 2, image1.height);
В настоящем примере ширина полотна image1 делится без остатка на два. Обратите
внимание, что делитель пишется не в скобках, а сразу после команды div.
Как написать на delphi генератор случайных чисел? Командой random,
после которой в скобках указывается максимальная величина генерируемого числа.
edit1.text:=inttostr(random(100)); //генератор случайных чисел в пределах
ста
А сейчас мы применим наши математические познания и создадим утилиту для решения
квадратных уравнений вида:
ax2+bx+c ? 0
Если вы учились в школе, то помните, что эти уравнения имеют два
корня, которые находятся по формуле
х1,2 = (-b±2^(b^2+4ac))/2a
Да, страшная формула… На форму бросайте компоненты trichedit, два
button'a - countbutton и exitbutton - и три labelededit'а, в которые вводятся,
соответственно, параметры a, b, c. Найдите у labelededit'ов свойство labelposition
и поставьте его в lpleft.
Мы будем работать с параметрами a, b, с и дискриминантом (для тех, кто не знает,
- сумма квадрата b и учетверенного произведения a и c). В delphi таких переменных
нет, мы сами их придумали, а потому нужно продекларировать их в var.
Удерживая нажатой клавишу shift, выберите все три labelededit'a
и по событию onkeypress поставьте у всех labelededit1keypress (и далее см. листинг):
procedure tform1.labelededit1keypress(sender: tobject; var key: char);
begin
if not (key in ['0'..'9','-', char(vk_back)]) then begin //вводить можно только
числа
beep;
key:=#0;
end;
end;
procedure tform1.closebuttonclick(sender: tobject);
begin
application.terminate; //гарантированно освобождает память - в отличие от close
end;
procedure tform1.countbuttonclick(sender: tobject);
var
a, b, c,
diskrim,
x1, x2: real;
begin
//если а=0 - прерываем процесс
if (labelededit1.text='0') or (labelededit1.text=emptystr) then abort;
//если данные не введены - ставим 0
if labelededit2.text=emptystr then labelededit2.text:='0';
if labelededit3.text=emptystr then labelededit3.text:='0';
//инициализируем переменные
a:=strtofloat(labelededit1.text);
b:=strtofloat(labelededit2.text);
c:=strtofloat(labelededit3.text);
//находим дискриминант
diskrim:=sqr(b) + 4*a*c;
if diskrim < 0 then begin //если он меньше нуля, уравнение не имеет смысла
richedit1.clear;
richedit1.lines.add('d<0. Корней нет!');
abort; //прерываем процесс
end;
b:=b*-1; //х1 и х2
a:=a*2;
x1:=(b + sqrt(diskrim))/a;
x2:=(b - sqrt(diskrim))/a;
//выводим результаты
richedit1.clear;
richedit1.lines.add('Решение:' + #10 + #10 +
'Находим дискриминант: d = ' + floattostr(diskrim) + #10);
if diskrim > 0 then
richedit1.lines.add('d>0. Уравнение имеет 2 корня.'+ #10 +
'x1=' + floattostr(x1) + '; x2=' + floattostr(x2));
if diskrim = 0 then
richedit1.lines.add('d=0. Уравнение имеет 1 корень.' + #10 +
'x=' + floattostr(x1));
end;
Ну вот мы и познакомились с некоторыми математическими возможностями.