Если в основную программу поместить оператор

writeln (' a=',a:5:2,' b=',b:5:2);,

то компиляция программа будет остановлена и в верхней части окна редактора в красной полосе будет выведено сообщение:

Error 3: Unknown identifier.,

при этом курсор редактора будет мерцать под именем формального идентификатора a:

writeln (' a=',a:5:2,' b=',b:5:2);.

Формальные переменные невидимы в основной программе, поэтому компилятор прекращает трансляцию программы и выдает сообщение об ошибке.

Если переменные a и b описать в основной программе:

var a, b, x, y, s: real;,

то компиляция программы пройдет, но на экран будет выведен результат:

x = 0.00 y = 0.00 s =< фактическое значение суммы >.

a = 0.00 b = 0.00.

Дело здесь в том, что переменные a и b, описанные в разделе var основной программы и формальные параметры процедуры – это различные переменные, хотя и имеющие одинаковые имена.

Для того, чтобы переменные x и y были доступны в основной программе, надо в заголовке процедуры формальные параметры a и b описать как параметры-переменные:

procedure vvod(var a, b: real);.

Принципиально возможно объявить все формальные параметры параметрами-переменными и таким образом избежать возможных осложнений при передаче информации в вызывающую программу. Однако по ряду причин это нецелесообразно, т.к. появляется возможность испортить фактические переменные. Поэтому следует объявлять параметрами-переменными только те параметры, через которые процедура действительно передает во внешнюю часть программы результаты вычислений процедуры.

Внутри блока используемые данные должны быть описаны заранее. Они могут быть описаны как в начале программы в списке описаний переменных, констант, типов и меток, так и в начале самой процедуры. Например, мы имеем следующую программу:

program prim6;

var

a,b: real; {глобальные переменные}

procedure s1;

var

i, k: real; {локальные переменные}

begin

{тело процедуры}

end;

var

z: real;

BEGIN

{тело программы}

END.

Переменные a, b, z являются глобальными, переменные i,k описаны как локальные в процедуре s1.

Глобальные переменные, константы, типы и метки – это те объекты, которые объявляются в программе вне процедур и функций. Глобальные объекты доступны в основном блоке программы, т. теле программы, и в блоках процедур и функций, описанных ниже.

Переменные a, b могут использоваться как в теле программы, так и в теле процедуры s1. Переменная z доступна только в теле программы.

Локальные объекты – это переменные, константы, типы и метки, существующие только внутри процедур или функций и объявленные либо в списке параметров, либо в разделах var, const, type, label внутри процедур или функций. В рассмотренном выше примере программы prim6 переменные i, k являются локальными для процедуры s1 и доступны только внутри ее.

Все описанные в некотором блоке имена имеют силу только для этого блока и вложенных в него блоков. При совпадении имен локальной и глобальной переменных сильнее оказывается локальное имя и именно оно используется внутри подпрограммы. Одноименные локальные и глобальные переменные – это разные переменные. Любое обращение к таким переменным рассматривается как обращение к локальным переменным, т.е. глобальные переменные в данном случае недоступны.

Объявление части переменных локальными повышает устойчивость программы к появлению возможных ошибок. В частности, если подпрограмма содержит циклы for, то параметры циклов целесообразно описывать как локальные переменные. Это позволит избежать затруднений при циклическом вызове процедур, если в качестве параметров циклов основной программы и вызываемых из нее процедуры используются переменные с одинаковыми именами.

Чем меньше параметров процедуры объявлено параметрами-переменными и чем меньше в блоке используется глобальных переменных, тем меньше опасность получить не предусмотренные программистом побочные эффекты, связанные с вызовом блока, тем проще программа в понимании и отладке.

Часто встречается случай, когда в ходе действия процедуры определяется какое-то значение только одного некоторого параметра. В этом случае процедура может быть представлена в виде функции.

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

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

2. Заголовок функции должен иметь вид:

function < имя функции > (< список ф.п.>:<тип ф.п. >): < тип результата >;.

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

3. Обращение к функции можно использовать в соответствующих выражениях наряду с переменными и константами.

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

program prim7; {z=ab}

varI

x, y, z: real;

function ab(a, b: real): real;

begin

if a>0 then ab:= exp(b*ln(a))

else if a<0 then ab:= exp(b*ln(-a))

else if b=0 then ab:=1 else ab:=0;

end;

BEGIN

write(‘x=’); readln(x);

write(‘y=’); readln(y);

z:=ab(x,y); {z=xy}

writeln(‘ z=’, z:6:3);

readln;

END.

Если, например, необходимо вычислить значение z по формуле

,

то, имея в программе описанную выше функцию, можно записать

z:=(ab(x,y)+3*ab(y,x))/4;.

Паскаль позволяет использовать рекурсии процедур и функций. Рекурсия – это такой способ организации вычислительного процесса, при котором процедура или функция в ходе выполнения составляющих ее операторов обращается сама к себе. Рассмотрим программу вычисления факториала .

program factorial;

var n: byte;

function fac(n: byte): extended;

begin

if n=0 then fac:=1 else fac:=n*fac(n-1);

end;

BEGIN

write(‘ n=’); readln(n);

writeln(n!=’, fac(n):10:0);

readln;

END.

Поскольку значения факториала растут очень быстро, то для описания типа функции целесообразно использовать тип extended.

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

Функцию вычисления факториала можно записать иным образом, используя цикл for:

function fac(n: byte): extended;

var

i: byte;

p: extended;

begin

p:=1;

for i:=1 to n do

p:=p*i;

fac:=p;

end;


Лекция 18. Модули Unit

Программа или ее отдельная часть может быть оформлена в виде модуля, который будет помещен в библиотеку модулей и может быть использован другими программами. Запись программ в виде модулей дает следующие преимущества:

1) Объем оперативной памяти для размещения программы в Турбо-Паскале не может превышать 64 КБ. Применение модулей позволяет разделить программу на несколько частей и тем самым избежать этого ограничения. При этом объем памяти для одного модуля также не должен превышать 64 КБ.

2) При отладке программы программа при каждом запуске компилируется целиком. Модули могут компилироваться отдельно, при этом после компиляции они получают расширение.tpu, с которым в дальнейшем используются в программах без повторной компиляции.

1) Отлаженные и записанные в виде модулей программы образуют библиотеку, отдельные элементы которой могут подключаться к другим программам. Поэтому программы, решающие общие задачи, целесообразно оформлять в виде модулей.

Модуль разделяется на несколько разделов: заголовок, интерфейсная часть, реализационная часть, инициализационная часть.

Заголовок модуля.

Он состоит из зарезервированного слова Unit и имени модуля, например,
unit s1. После имени ставится точка с запятой. В отличие от имени программы имя модуля должно совпадать с именем файла, в котором он хранится. Поэтому имя модуля не может состоять более чем из восьми символов. Так же, как и в программе, имя модуля не может совпадать с именами объектов, используемых в модуле. В модуле unit s1 не должно быть переменных, констант, меток перехода, процедур и функций с именем «s1».

Интерфейсная часть.

Блок начинается с зарезервированного слова interface. По отношению к программе эта часть является новой. В этой части описываются все константы, типы данных, переменные, процедуры и функции, доступные в этом модуле для использования внешними программами.

Интерфейсная часть составляет так называемую «видимую» часть модуля. В этой части можно сделать доступными для использования уже существующие готовые модули, указав их имена после слова Uses. Следом за оператором uses описываются доступные извне и необходимые для описания процедур и функций определения типов данных, констант и переменных. Глобальные элементы (типы, константы и переменные) могут использоваться в основной программе и при этом необязательно использоваться в данном модуле.

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

Реализационная часть.

Блок начинается с зарезервированного слова implementation. В этом разделе описываются процедуры и функции, заголовки которых приведены в интерфейсной части, а также блоки, являющиеся локальными для данного модуля и которые не могут быть вызваны непосредственно из основной программы. Здесь также могут быть описаны глобальные для данного модуля переменные, константы и типы данных.

Интерфейсная часть, также как и реализационная часть, могут быть пустыми, т.е. не содержать ни одного описания.

Инициализационная часть.

Этот раздел завершает модуль. Он может быть отсутствовать вместе с начинающим его словом BEGIN или быть пустым. Тогда вслед за словом BEGIN должен находиться признак окончания модуля - слово END. с точкой на конце.

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

Для примера рассмотрим программу с именем «pr1», в которой задаются интервалы изменения аргумента, а подключаемый модуль с именем «integr» вычисляет площадь, ограниченную параболой, пределами изменения этой функции, графиком функции и осью абсцисс (вычисляется интеграл от этой функции).

Пример записи:

program pr1;

uses crt,integr;

{var }

a,b,s:Real;

{ n:integer; }

Begin

write('a=');readl(a);

write('b=');readl(b);

write('n=');readl(n);

czet;

writeln(‘S=’,s:6:4);

readln;

END.

Процедура cze t, вычисляющая площадь под кривой, находится в модуле integr. Используемые в основной программе переменные a,b,s,n должны быть описаны заранее. Эти переменные используются также в модуле integr. Если их описать в основной программе, то они будут недоступны в модуле. Если их описать в и в основной программе, и в модуле, то получим различные переменные. При этом введенные в программе значения a,b не будут восприняты в модуле, а рассчитанное значение суммы S в модуле нельзя будет передать в основную программу. Поэтому эти переменные описываются как глобальные в интерфейсной части модуля. Переменные i,h используются только в модуле, поэтому они описываются в реализационной части.

Настройки программы в данном случае не требуется, инициализационный блок в данном примере пустой. В нее можно было поместить, например, из реализационного блока оператор s:=0;

unit integr;

interface

var

s,a,b: real;

n:integer;

procedure czet;

implementation

var

i: integer;

h: real;

function fun(x:real):real;

begin

fun:=sqr(x);

end;

procedure czet;

begin

s:=0;

h:=(b-a)/n;

for i:=1 to n do

s:=s+fun(a+(i-0.5)*h);

s:=s*h;

end;

BEGIN

end.

Для дальнейшей работы модуль должен быть откомпилирован, то есть получен файл с тем же именем и расширением. tpu. Для компиляции файлов в Турбо-Паскале предусмотрен раздел главного меню Compile. В этом разделе имеются три режима компиляции:

Ø Compile;

Ø Make;

Ø Bulid.

При компиляции модуля или основной программы в режиме Compile все упоминающиеся в разделе uses модули должны быть предварительно откомпилированы и результаты компиляции помещены в одноименные файлы с расширением.tpu.

В режиме Make компилятор проверяет:

Ø Наличие tpu-файлов для каждого объявленного модуля. Если какой-либо файл не обнаружен, то система пытается отыскать одноименный файл с расширением. pas, то есть файл с исходным текстом модуля. Если pas-файл найден, система приступает к его компиляции.

Ø Соответствие tpu -файла исходному тексту модуля, куда могут внесены изменения. Если исходный файл был изменен, то tpu-файл автоматически создается заново.

Ø Неизменность интерфейсного раздела модуля. Если этот раздел изменился, то перекомпилируются все модули, в начале которых данный модуль указан в разделе uses, то есть все модули, использующие данный модуль.

Если все модули перекомпилированы, давно проверены и неизменны, то в режиме Make система работает только с tpu -файлами, время компиляции минимально.

В режиме Build существующие tpu -файлы игнорируются. Система пытается отыскать и откомпилировать соответствующие pas-файлы для каждого объявленного в разделе uses модуля. Таким образом, этот режим требует наличия исходных текстов модулей. Перестраховка в компиляции всех без исключения модулей приводит к увеличению продолжительности компиляции.


Лекция 19. Текстовый редактор Турбо-Паскаля.

Для написания и редактирования программ используется текстовый редактор Турбо-Паскаля. После загрузки Турбо-Паскаля режим редактирования устанавливается автоматически. Признаком того, что среда Турбо-Паскаля находится в состоянии редактирования, является наличие в окне редактора курсора - небольшого мигающего прямоугольника. Из режима редактирования можно перейти к любому другому режиму Турбо-Паскаля с помощью функциональных клавиш или выбора нужного режима из главного меню. Если среда находится в состоянии выбора из меню, курсор исчезает, а в строке меню появляется цветной указатель - прямоугольник, выделяющий одно из кодовых слов. Для перехода из состояния выбора режима из главного меню в состояние редактирования надо нажать клавишу Esc, для перехода в главное меню - клавишу F10 или щелкнуть мышкой по строке меню.

Редактор позволяет разрезать и склеивать строки. Для того, чтобы разрезать строку, следует подвести курсор к нужному месту и нажать клавишу Enter. Чтобы соединить две строки, надо установить курсор в конец первой строки, например, клавишей End и нажать клавишу Delete или, установив курсор в начало второй строки клавишей Home и нажать клавишу Backspace (клавиша со стрелкой).

Нормальный режим редактора - это режим вставки, в котором каждый вновь вводимый символ как бы раздвигает текст на экране, смещая вправо текст строки. Следует иметь в виду, что разрезание и последующая вставка пропущенных строк возможны только в этом режиме. Редактор может работать также в режиме замены, т.е. наложения новых символов на существующий старый текст. В этом режиме новый символ заменяет собой тот старый символ, на который указывает мигающий курсор, а остаток строки справа не сдвигается вправо. Для перехода в режим замены нужно нажать клавишу Insert. Если нажать эту клавишу еще один раз, то вновь восстановится режим вставки.

Признаком того, в каком режиме находится редактор, является форма курсора. В режиме вставки курсор похож на мигающий символ подчеркивания, а в режиме наложения он представляет собой крупный мигающий прямоугольник, заслоняющий символ целиком.

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

Для того, чтобы часть текста воспринималась как блок, необходимо ее выделить. Выделенный блок отмечается более светлым фоном строк. Выделить блок можно несколькими способами.

1) Используя клавиши перемещения курсора, установить курсор в начало блока и нажать клавиши Ctrl+K,B. Затем переместить курсор в конец блока и нажать клавиши Ctrl+K,K.

2) Используя клавиши перемещения курсора, установить курсор в начало блока. Затем нажать клавишу Shift, и удерживая ее, переместить курсор на последний символ блока, после чего клавишу отпустить.

3) Перемещая мышь, установить указатель мыши на символ, с которого начинается блок. Далее нажать левую кнопку мыши, и удерживая ее, переместить его на последний символ блока. Затем клавишу мыши отпустить.

С выделенным блоком возможны следующие основные операции:

Ø удаление;

Ø копирование;

Ø печать;

Ø запись во внутренний буфер;

Ø вставка из внутреннего буфера;

Ø запись на дисковый файл;

Ø чтение с диска.

Для работы с редактором в пункте главного меню Edit (правка) собраны основные команды. При входе в это меню открывается подменю с командами

Undo (откат)

Redo (откат отката)

_______________

Cut (вырезать)

Copy (копировать)

Paste (вставить)

Clear (очистить)

_______________

Show Clipboard (показать карман)

В том случае, если вы вносите исправления в написанную ранее строку и хотели бы вернуться к ее первоначальному виду, надо выбрать команду Undo. Для возвращения к измененному виду используется команда Redo.

В оперативной памяти компьютера при работе с Турбо-Паскалем организуется временный буфер, или карман, куда на время работы могут быть помещены элементы программы.

Для удаления выделенного блока из программы необходимо набрать Ctrl+K,Y или в меню Edit выбрать команду Clear, или набрать Ctrl+Del. В этом случае выделенный блок удаляется, не сохраняясь в буфере. Возвратить его можно только с помощью команды Undo меню Edit.

Команда Cut записывает выделенный блок в карман, а затем удаляет его из программы. Эта операция выполняется также при нажатии клавиш Shift+Del.

Команда Copy копирует выделенный блок в карман, при этом блок остается в основной программе. Команда выполняется также при нажатии клавиш Ctrl+Ins.

Для вставки выделенного блока необходимо установить курсор в место, где должно быть начало вставки, и нажать клавиши Ctrl+K,C. Если блок помещен в карман, то можно установить курсор в место вставки и выбрать команду Paste. Эта же команда выполняется при нажатии клавиш Shift+Ins. Командой Ctrl+K,C можно вставить выделенный блок только в пределах одной программы. Турбо-Паскаль версий 6.0 и 7.0 позволяет работать одновременно с несколькими программами, находящимися в различных окнах. Здесь можно войти в одну программу, выделить интересующий блок, поместить этот блок в карман командой Copy, затем открыть окно с другой программой, курсором указать место вставки и командой Paste вставить блок во вторую программу.

Выделенный блок можно записать в виде отдельного файла. Для этого надо нажать Ctrl+K,W. На экране появится окно с запросом, куда и под каким именем записать блок. Если вы хотите поместить этот блок на дискету, то надо указать А:\< имя файла >. Если указать только имя файла, то блок будет записан в тот каталог, откуда была вызвана ваша программа или в основной каталог Турбо-Паскаля. Расширение. pas можно не указывать, среда Турбо-Паскаля добавит его самостоятельно.

Если вы хотите вставить в свою программу часть другой, записанной на дисках, надо набрать Ctrl+K,R. После этого появится строка запроса, в которой надо указать путь к вставляемому файлу, и нажать Enter.

Для снятия выделения блока надо нажать клавиши Ctrl+K,H. Повторное нажатие этой комбинации клавиш возвращает выделение блока.

Текст выделенного блока можно распечатать на матричном принтере, нажав клавиши Ctrl+K,P.

При отладке программы иногда требуется найти в программе место, где находятся некоторые операторы или идентификаторы. Если программа достаточно большая, то непосредственный поиск может потребовать значительных усилий. Для этого можно воспользоваться командами главного меню Search. При входе в меню открывается подменю:

Find...

Replace...

Search again

_______________

Go to line number...

Show last compiler error

Find error...

Find procedure...

_______________

Поиск нужной последовательности символов можно выполнить по команде Find. Эта же команда выполняется при нажатии клавиш Ctrl+Q,F.

При обращении к команде открывается окно с одним так называемым триггерным списком и тремя селективными списками.

В строку ввода признаков поиска необходимо записать фрагмент текста, который требуется найти в тексте программы.

Триггерный список допускает включенное состояние нескольких элементов, обозначаемое знаком [X]. Включение и выключение пункта выполняют мышью или клавишей пробела.

Селективный список позволяет отмечать точкой (·) и выбирать только один элемент из списка.

Если нужно, чтобы строчные и прописные буквы при поиске различались, включают пункт Case sensitive. Этот пункт действует только для латинских букв.

Если включить пункт Whole words only, то будут отыскиваться только фрагменты, у которых совпадают концы слов. Например, для образа «Глава 1» не будет найден фрагмент «Глава 11». При отключении этого пункта находятся все фрагменты, начинающиеся с указанных в строке поиска начальных символов.

Пункт Regular expression организует поиск по описателю текста, когда полностью искомый текст неизвестен и указываются допустимые отклонения (отмечаются место и возможное количество неопределенных символов, возможные варианты и т.д.).

Список Direction определяет направление поиска. Включение пункта Forward указывает направление поиска от начала до конца текста, пункт Backward организует поиск от конца текста программы к началу.

В разделе Scope указывается место поиска. Если в тексте программы выделен блок, то включение пункта Selected text организует поиск внутри выделенного блока, при включении пункта Global поиск проводится по всему тексту программы.

Раздел Origin определяет место начала поиска. При включении пункта Entire scope поиск начинается с начала или конца текста программы в зависимости от настройки раздела Direction. При включении пункта From cursor поиск начинается с места программы, где установлен курсор.

Для разового поиска включают пункт Find..., устанавливают соответствующие пункты и для начала поиска нажимают клавишу Enter или ОК. После разового поиска для нахождения следующих позиций соответствующей комбинации символов выбирают пункт Search again.

Для замены найденного фрагмента на новый выбирают пункт меню Replace. В этом случае открывается окно, подобное окну Find, но с дополнительной строчкой New text. В это окно надо занести новый текст, который должен заменить старый. Также имеется дополнительный пункт Promt on replace. Если его включить, то перед каждой заменой будет появляться запрос:

Replace this occurence? (Здесь заменять?) и три ответа «Yes», «Not» и «Cancel».

Также имеется пункт Change. all. При его включении производится поиск и замена всех обнаруженных фрагментов текста.

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


Управление экраном. Модуль Сrt.

В турбо-Паскале имеется библиотека модулей, содержащих некоторые дополнительные процедуры и функции. Модуль crt содержит ряд подпрограмм, позволяющих управлять режимами экрана, устанавливать цвет фона и символов, отображать на экране окна и подавать звуковые сигналы.

Для того, чтобы использовать программы модуля, надо указать имя модуля в списке оператора uses:

Uses crt;

Для управления цветом экрана используются следующие процедуры:

TextColor(color:byte);

устанавливает цвет отображаемых на экране символов.

TextBackground(color:byte);

устанавливает цвет фона.

Для этих процедур определен набор констант цветов, приведенных в табл. 19.1.

Таблица 19.1.

Соответствие констант и цветов экрана.

Имя Числовое значение Цвет
Black   черный
Blue   синий
Green   зеленый
Cyan   голубой
Red   красный
Magenta   фиолетовый
Brown   коричневый
LightGray   светло-серый
DarkGray   темно-серый
LightBlue   светло-синий
LightGreen   светло-зеленый
LightCyan   светло-зеленый
LightRed   светло-красный
LighMagenta   светло-фиолетовый
Yellow   желтый
White   белый
Blink   мерцание

Константы с значениями 0-7 могут применяться как для фона, так и символов, константы с значениями 0-15 применяются только для символов. Если для фона будет указана константа со значением выше 7, то фон экрана будет выбран по номеру в диапазоне 0-7, определенному по разности между указанным в процедуре textbackground и числом, кратным 8. Константа Blink задает мерцание отображаемых символов. Она обычно используется в процедуре textcolor в качестве слагаемого, например,

TextColor (Blue+Blink) или TextColor (1+128) или TextColor (129).

Для того, чтобы очистить экран, применяется процедура Clrscr. При этом с экрана убираются находящиеся на нем ранее символы, а курсор перемещается в верхний левый угол.

Модуль Crt позволяет создавать дополнительные окна на экране с помощью процедуры Window (x1, y1, x2, y2: word);.

Эта процедура образует окно, которое становится текущим, и все операции с экраном относятся к той части, которая определена координатами x1, y1, x2, y2. При этом перемещение курсора происходит только в пределах текущего окна.

Координаты x1, y1, x2, y2 всегда отсчитываются от левого верхнего угла экрана и должны удовлетворять следующим условиям:

Если эти условия не выполняются, то окно создано не будет. xmax и ymax зависят от типа видеосистемы. В нашем вычислительном центре. xmax =80, ymax =25.

При завершении работы программы, использующей окна, происходит автоматическое восстановление параметров текстового режима, установленных перед запуском программы, и текущим окном становится весь экран.


Лекция 20. Машинная арифметика и ошибки вычислений

Достоверность полученной в результате моделирования информации зависит от точности математического описания реальной проблемы и от погрешностей, возникающих при решении математической задачи. Математическая модель создается на основании наших знаний о проблеме, при этом учитывается возможность нахождения неизвестных параметров модели доступными методами. Погрешности вычислений связаны с ошибками округлений дробных чисел и неустойчивой работой вычислительных алгоритмов, когда оказывается невозможным за конечное число шагов найти решение с приемлемой точностью.

Применение компьютеров существенным образом расширяет вычислительные возможности и позволяет обращаться к таким задачам, которые принципиально не могли быть поставлены при вычислениях с помощью ручки и бумаги. Однако, при этом появились дополнительные источники возникновения ошибок. В ручных вычислениях промежуточные результаты непосредственно доступны для обозрения, и процесс расчета можно корректировать в соответствии с получаемыми результатами. При этом ручные вычисления обычно не бывают длинными, тогда как машинный процесс вычислений может состоять из миллионов шагов. Ничтожно малые ошибки, которыми в коротком вычислении можно было бы пренебречь, накапливаясь в протяженном процессе, могут приводить к разрушительным последствиям. Кроме того, методы, вполне удовлетворительные для малых задач, могут быть безнадежно неэффективными для больших задач того же типа.

Иногда компьютерные программы не замечают существенных ошибок, выводят информацию об успешном завершении расчетов и показывают полученные результаты, которые могут существенно отличаться от истинных. Поэтому в процессе разработки компьютерных программ следует помнить об источниках возникновения возможных ошибок и предусматривать соответствующие меры для их обнаружения и предупреждения.

В машинных вычислениях участвуют числа двух типов: целые числа и вещественные числа (так называемые числа с «плавающей запятой»). В отличие от общепринятой арифметики с десятичной системой исчисления работа компьютеров основана на двоичной системе чисел, т.е. в виде последовательностей нулей и единиц, при этом всегда для представления любого числа в памяти компьютера выделяется строго ограниченное количество разрядов. В частности, языке программирования Турбо-Паскаль для целых чисел типа byte выделяется один байт машинной памяти, поэтому переменные данного типа могут принимать значения в диапазоне от 0 до 28-1=255. Для хранения целых чисел типа word и integer выделяются 2 байта памяти, поэтому для типа word, в котором могут быть представлены только неотрицательные числа, диапазон допустимых значений ограничен величинами от 0 до 216-1=65535. Числа типа integer могут быть положительными или отрицательными, их диапазон ограничен значениями от до . Если работать с целыми числами, далекими от границ числовой области компьютера, то машинная арифметика дает правильные результаты, например 5+7=12, 8-27=-19, 27´3=81 и т.д. Деление целых чисел снова приводит к целому числу, а в качестве результата операции принимается частное, а остаток отбрасывается. Это означает, что и т.д.

Если результат операции над целыми числами слишком велик или слишком мал для данного типа переменных, то при отсутствии контроля за превышением допустимого диапазона результат будет заменен по циклическому правилу. Например, если переменным a и b присвоить тип byte, переменной a присвоить значение a=255, а переменной b – значение b=a+ 1, то компьютер выдаст результат: b =0, при b=a +2 получим b =1 и т.д. Если a и b отнести к переменным типа integer и присвоить a =32767, то при b=a +1 получим b =-32768, при b=a +2 ® b=-32767. Эти ошибки не будут замечены, и программа продолжит дальнейшую работу с неверными значениями переменных.

Если в программе предусматривается проверка переполнения допустимого диапазона переменных, то при выходе значения за пределы диапазона на экран выводится сообщение об ошибке, а работа программы приостанавливается.

Десятичные числа вещественного типа с «плавающей запятой» представляются в виде . Число a называется мантиссой, а b – показателем. Обычно число b целое, а у числа a слева от десятичной запятой находится только один знак. У обоих чисел a и b количество разрядов конечно, поэтому имеется лишь конечное множество чисел с плавающей запятой и, в частности, существуют наибольшие и наименьшие числа с плавающей запятой.

Если результат операции превышает наибольшее значение, то происходит переполнение выделенных ячеек памяти, и работа программы на этом прекращается. Если результатом операции является число, слишком близкое к нулю, то происходит исчезновение порядка. Компьютер заменяет результат нулем без какого-либо сообщения об этой операции. Во многих случаях подобная замена не приводит к появлению заметных погрешностей в окончательном результате, однако, иногда подобные округления при операциях умножения и последующего деления, сложения или вычитания малых по абсолютной величине чисел могут вызвать принципиальные ошибки результатов вычислений.

Наибольшее значение, при котором происходит обнуление результата, называется машинным нулем. Эта величина зависит от типа переменных, с которыми производятся операции, численного значения переменных и типа компьютера. Для оценки погрешности округления используется понятие машинного эпсилон eмаш, численно равного наименьшему числу, которое при сложении с вещественным числом 1 дает результат, больший чем 1. Величину eмаш можно определить с помощью следующей программы:

Program Nul;

var

x, eps: real{single, double, extended};

BEGIN

eps:=1;

repeat

eps:=eps/2;

x:=1+eps;

until x<=1;

writeln(‘eps=’,eps);

readln;

END.

В табл.20.1. приведены результаты тестирования компьютера Pentium с различными типами данных при операции сложения x=A+e0.

Таблица 20.1. Результаты вычисления машинного нуля e0

  Тип переменных А
     
single 5,96´10-8 1,19´10-7 3,82´10-6
real 4,55´10-13 9,05´10-13 2,91´10-11
double 1,11´10-16 2,22´10-16 7,11´10-15
Extended 5,42´10-20 1,08´10-19 3,47´10-18

Наличие машинного эпсилон проявляется следующим образом. Например, запись вещественного числа 0,3 в память компьютера сопряжена с ошибкой, поскольку величина 0,3 не имеет точного двоичного представления в системе вещественных чисел с плавающей запятой. Поэтому сумма десяти шагов длиной 0,3 не будет точно равна одному шагу длиной 3,0. Подобные малые ошибки при длительных расчетах могут накапливаться и приводить к более заметным суммарным ошибкам.

Погрешность представления вещественного числа в программе локализуется в последнем бите памяти. Более серьезные последствия может вызвать неудачное использование вычислительных алгоритмов.

Рассмотрим пример вычисления значений функции . Эта функция может быть представлена как сумма бесконечного ряда

. (20.1)

В практических расчетах всегда ограничиваются только несколькими членами ряда, отбрасывая величины, не влияющие на окончательный результат. В табл.20.2 и 20.3 приведены точные значения функции и результаты вычисления с помощью ряда различной длины для некоторых значений параметров.

Таблица 20.2

Точные и рассчитанные с помощью ряда значения функции y=ex при представлении вещественных чисел типом real.

  X   Точное Значение y=ex Длина ряда
для всех х при x ³ 0; при x <0.
       
-30 9,358´10-14 8,782´108 -2,588´10-1 -2,588´10-1 9,360´10-14
-20 2,061´10-9 1,047´100 3,505´10-5 3,505´10-5 2,061´10-9
-10 4,540´10-5 4,540´10-5 4,540´10-5 4,540´10-5 4,540´10-5
           
  2,203´104 2,203´104 2,203´104 2,203´104 2,203´104
  4,852´108 4,852´108 4,852´108 4,852´108 4,852´108
  1,069´1013 1,068´1013 1,069´1013 1,069´1013 1,068´1013

В диапазоне значений [-10,+30] при 50 членах ряда рассчитанные по (1.1) значения практически полностью совпадают с точными, определенными по более сложному алгоритму. Однако при x=-20 ошибка расчета составляет 9 порядков, а при x = - 30 - 22 порядка. Увеличение длины ряда до 100 членов снижает расхождения между точными и расчетными значениями, но не приводит к точному результату. Дальнейшее увеличение длины ряда до 500 членов не оказывает заметного влияния на результаты расчета.

Представление вещественных чисел типом extended с 19-20 значащими цифрами позволяет при 100 членах ряда получить практически точное значение для x = - 20, однако при x = - 30 ошибка вычисления составляет 6 порядков. Эта погрешность сохраняется при дальнейшем увеличении длины ряда.

Таблица 20.3

Точные и рассчитанные с помощью ряда значения функции y=ex при представлении вещественных чисел типом extended.

  X   Точное Значение y=ex Длина ряда
для всех х при x³0; при x<0.
       
-30 9,358´10-14 8,782´108 -5,736´10-8 -5,736´10-8 9,360´10-14
-20 2,061´10-9 1,047´100 2,060´10-9 2,060´10-9 2,061´10-9
-10 4,540´10-5 4,540´10-5 4,540´10-5 4,540´10-5 4,540´10-5
           
  2,203´104 2,203´104 2,203´104 2,203´104 2,203´104
  4,852´108 4,852´108 4,852´108 4,852´108 4,852´108
  1,069´1013 1,068´1013 1,069´1013 1,069´1013 1,068´1013

Результаты расчета показывают, что вычисление функции с помощью ряда хорошо приближается к точным значениям при положительных значениях аргумента, но дает неустранимые и существенные погрешности при отрицательных значениях. Увеличить точность вычислительного алгоритма можно достаточно просто, используя для отрицательных аргументов формулу

. (20.2)

Вычисленные по этому ряду значения приведены в правых столбцах табл. 20.2 и 20.3.

Следует обратить внимание еще на класс так называемых плохо обусловленных задач, для которых малое изменение входящих в уравнения коэффициентов приводит к значительному изменению результата. Примером таких задач является решение систем линейных уравнений, когда входящие в систему уравнения соответствуют почти параллельным прямым. Небольшое изменение в пределах погрешности округления численных значений угловых коэффициентов может значительно переместить точку пересечения прямых. К таким же последствиям приводит решение квадратного уравнения при или нахождение корней многочлена высокой степени. Для этого класса задач необходимо предусматривать дополнительные меры, позволяющие довести ошибки округления до безопасного уровня.

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


Лекция 21. Решение нелинейных уравнений.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: