===== Округление ===== ==== Функция 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 была пустая');