===== Округление =====
==== Функция Round ====
Округление, которое берёт любой "действительный" тип (//real//, //extended// и т.д.), а возвращает целое число (//integer//).
Имеет малоизвестную особенность - "половинки" округляет до ближайшего чётного числа, т.е.
Round(3.5) = 4
но
Round(6.5) = 6
В остальных случаях работает без затей:
Round(3.05) = 3
Round(3.55) = 4
Round(6.05) = 6
Round(6.55) = 7
===== Функция Random и компания =====
==== Random ====
Функция //Random// используется для получения случайных чисел.
Случайные числа служат, например, для генерации природных объектов, для имитации элемента случайности в играх и т.д. Одно из важных применений данной функции - получение неизвестных заранее исходных данных либо данных, имеющих значительный объём, при тестировании программ.
Функция //Random// имеет **две формы (!)**, одна из которых возвращает случайные "действительные числа" из стандартного интервала [0,0; 1,0), а вторая - "натуральные числа" (и 0) из диапазона, определяемого параметром.
//Random: Extended//;
и
//Random( Range: Word): Word//;
Если параметр //Range// не указан, то результатом будет случайное число //X// типа //Extended// в диапазоне между 0 (включительно) и 1. Если целочисленный параметр //Range// определен, то результатом будет неотрицательное случайное число //X// в диапазоне между 0 (включительно) и //Range//. **Обратите внимани**е - сам //Range// никогда не возвращается!
Program DemoRandom;
Const
N=100;
Var
i : integer;
A : array [1..N] of integer; // Массив из 100 целых элементов
Begin
randomize; // "Взводим" случайные числа
for i:= 1 to N do
A[i] := 1 + random(10); // Получаем случайное число от 0 до 9 и "сдвигаем" его на единицу.
for i:= 1 to N do
write(A[i], ' ');
End.
==== Randomize ====
Также обратите внимание на процедуру //randomize//, которая "взводит" случайные числа. Без неё при каждом вызове программы "случайные числа" будут повторяться. Дело в том, что числа, возвращаемые функцией //random// не случайные, а **псевдослучайные** т.е. похожие на случайные. Случайность их определяется не тем, что нельзя точно предсказать следующее число, а тем что мы не знаем деталей алгоритма.
Одним из ключевых свойств алгоритма является то, что для одинаковых исходных данных, он должен выдать одни и те же итоговые значения. В противном случае, либо мы учли не все исходные данные, илибо это не алгоритм в классическом понимании!
Program DemoRandom;
Var
Q : real;
Begin
randomize;
Q := 99.0 * random + 1.0;
writeln (Q:5:2);
End.
Ниже приведены характерные ошибки.
Var
A:array[1..N] of integer;
i:= integer;
...
randomize;
for i:= 1 to N do
A[i] := random; // несовпадение типов!
...
for i:= 1 to N do
A[i] := random(10); // похоже, потерян randomize
...
for i:= 1 to N do
begin
randomize;
A[i] := random(10); // лишние randomize - рекомендуется посмотреть, что будет
end;
...
{ Пытаемся случайным образом заполнить массив неповторяющимися значениями.
Так делать не надо !!!! }
randomize;
for i:= 1 to N do
begin
A[random(N)] := i; // Диапазон возвращаемых random(N) значений - от 0 до N-1
// не совпадает с диапазоном индексов от 1 до N у массива
// array[1..N] of integer независимо от значения N
end;
...
i := randomize(10); // что-то не так :-)
===== Строковые процедуры и функции =====
==== Процедура Str ====
При составлении разделов //Val// и //Str// использовались материалы сайта [[http://www.pascaler.ru|http://www.pascaler.ru]]
Общий вид //Str//(//Chislo//,var //Stroka//)
**Процедура (не функция!)** //Str// преобразовывает **любое числовое значение** //Chislo// в строковую **переменную (важно!)** //Stroka//. После первого параметра может указываться формат, аналогично формату вывода в стандартных процедурах //write// и //writeln//.
Program DemoProcedureStr;
Var
Stroka : string;
Chislo : integer;
Begin
Chislo := 1560;
Str(Chislo:8, Stroka);
writeln(Stroka); {выводится строка ' 1500'}
Str(sin(Pi/5):6:4, Stroka);
writeln(Stroka); {выводится значение sin(π/5) с четырьмя знаками "после запятой":-)}
End.
==== Процедура Val ====
Общий вид Val(Stroka: String; var Chislo: <число>; Code:<число>)
Процедура //Val// преобразует значение строки //Stroka// в величину целочисленного или вещественного типа и помещает результат в //Chislo//. Значение строковой переменной //Stroka// не должно содержать пробелов в начале и в конце.
//Code// - целочисленная переменная типа //Word//. Если во время операции преобразования ошибки не обнаружено, значение //Code// равно нулю. Если же ошибка обнаружена, //Code// будет содержать номер первого ошибочного символа, а значение //Chislo// будет считаться не определенным (на практике там обычно лежит значение, соответствующее "правильной части" строки, т.е. число, которое было записано до некоректного символа).
Program DemoProcedureVal;
Var
Word : string;
Chislo, Code : integer;
Begin
writeln('Введите строку цифр ');
readln(Word);
Val(Word, Chislo, Code); {преобразование строки в число}
if Code <> 0 then
writeln('Ошибка! В позиции ',Code,' не верный символ!',);
End.
==== Функция Length ====
Общий вид Length(S:String):<число>
Функция //Length// возвращает действительно используемую ("актуальную") длину строки в символах, т.е число символов, которые в строку записали мы, а вернее - написанная нами программа. Эта длина закодирована в нулевом элементе строки, который никогда Length не учитывается.
Определить длину всей строки (размер выделенной под неё памяти) в байтах можно с помощью функции SizeOf.
If length(S)=SizeOf(S)-1 then
write('Строка заполнена полностью.');
If length(S) <> order (S[0]) then write ('Так быть не должно !!!')
**Обратите внимание, что при использовании кириллицы могут быть проблемы!**
В некоторых кодировках (включая нашу UTF-8) на латиницу отводится всего один байт памяти, а на кириллицу - больше! Это вызывает вопросы к реализации используемой библиотеки Паскаля.
==== Функция Concat ====
Общий вид //Concat(String1, String2 .. StringN: String): String//
Функция с произвольным числом строковых аргументов, которые "сливаются" в общую строку. "Лишние" символы - обрезаются без предупреждения. То же самое делает операция "+".
var
S1,S2 :string;
S :string[20]; // Укороченная строка - не более 20 символов
Begin
...
If Concat(S1, S2) <> S1+S2 then // два одинаковых слияния двух строк
write ('Ошибка в мироздании!');
S:= Concat(S1, S2);
If Concat(S1, S2) <> S then // тип Concat - полный 255 байтовый String
write ('Вполне возможно!');
If SizeOf (S) < SizeOf ('Не полезет ни за что!') then
begin
S := Concat('Не ', 'полезет ', 'ни за что!'); // а здесь уже три аргумента!
end;
End.
==== Pos ====
Общий вид //Pos(String1,String2: String):Position;//
Функция Pos возврашает позицию, начиная с которой во втором аргументе, строке String2, первый раз встречается первый - строка String1. Если String1 ни разу не встречается в String2, то возвращается 0!
If Pos('MA', 'MAMA') = 3 then
write('Что-то у нас не то набрано! Наверное перепутали кириллицу и латиницу в слогах слова "MAMA"!');
If Pos('MA', 'MAMA') = 0 then
write('Что-то у нас совсем не то набрано! Наверное перепутали кириллицу и латиницу в аргументах!');
==== Функция Copy ====
Общий вид //Copy(S:String; P, N):String//
Функция Copy возвращает строку, повторяющую N символов строки S, начиная с позиции N. Если символов не хватает ( P+N > Length(S)), то итоговая строка обрезается!
String2:= Copy('string1', P, N)
If String2 = 'string' then // из строки "string1" скопировали в строковую переменную String2 часть текста "string"
Write ('P = 1, N=6'); // т.е. шесть первых символов
==== Процедура Insert (вставка) ====
Общий вид //Insert(S1:String; var S2:String; P);//
Процедура Insert "портит" строку S2, вставляя начиная с позиции P подстроку S1, а оставшиеся символы строки S2, начиная с прежнего символа номер P, дописываются уже за ней. Если результат слишком длинный, то итоговая строка обрезается!
...
Insert('string1', S2, 1);
If S2 = 'string1' then // в начало строки S1 вписали "string1"
Write ('S2 была пустая'); //
==== Процедура Delete (удаление) ====
Общий вид //Delete(var S1:string; P, N);//
Процедура Delete "портит" строку S1, удаляя N символов, начиная с позиции P. Если следующие за ними символы существовали, то они продолжаются с позиции P.
...
S1 := S2;
Delete(S1, 1, length(S1));
If S1 = S2 then
Write ('S2 была пустая');