Современное программирование предлагает пользователям использовать самые разнообразные языки программирования. Но основой основ является Паскаль.Данный язык был разработан в 1971 году в Университете Цюриха профессором Никлаусом Виртом. Его предназначение изначально было учебным. Имея достаточно четко выраженную структуру и систему предоставления данных Паскаль имел ограничения в функциях ввода - вывода, при создании подпрограмм.

Практическое занятие

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

∆ = |A - a|

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

∆a >= ∆ = |A - a|

Абсолютная погрешность не единственная характеристика ошибки. Сравним 2 варианта результата с одинаковой погрешностью: 100 +/- 1 и 1 +/- 1. Очевидно, что нужно иметь характеристику, позволяющую учитывать само значение. Такой характеристикой является относительная погрешность - отношение абсолютной погрешности числа к его модулю (A<>0):

b = ∆ / A

Учитывая, что точное значение A обычно неизвестно, в качестве предельной относительной погрешности или "оценки сверху" относительной погрешности можно использовать значение:

ba = ∆a / (a - ∆a)

Погрешность результата вычислений складывается из погрешностей:

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

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

Например:

Задание 1. Выполнить оценку погрешности представления числа 1 / 3 и вычислений над числами типа real.

Составляем программу:

Program ex;

Var y, y1, y2, y3, y4, y5, y6, p:real

Begin

y:=1

y1:=y/3

WriteLn (`y1=`, y1:16:14); {выводит y1 = 0.33333333333348}

y2:=sqrt(y1);

y3:=sqrt(y2)

y4:=y3/14

y5:=y4*14

y6:=y5*3

WriteLn (`y6=`, y6:16:14); {выводит y6 = 1.00000000000182}

WriteLn (`y=`, y:16:14); {выводит y = 1.00000000000000}

End.

Отсюда, погрешности представления числа 1/3 в формате real:

∆ 1/3 = |1/3 - y1| = |0.33333333333333 - 0.33333333333348| = 0.15 * 10-12

b1/3 = 0.15 * 10-12 * (1/3) = 0.45 * 10-10

Погрешность выполнения операций над числами, представленными в формате типа real, в конкретном случае:

∆y6 = |y - y6| = |1 - 1.00000000000182| = 0.182 * 10-11

by6 = ∆y6 / y = 0.182 * 10-11/1 = 0.182*10-11

Задание 2. Из математики известно, что ch2x - sh2x =1. Разработать программу, проверяющую это равенство. Наша программа должна вводить значение x и для него считать:

y1 = (ex + e-x) / 2

y2 = (ex - e-x) / 2

y = y12 - y22

Полученные значения y1, y2 и y выведем на экран:

Program ex;

Var x, y, y1, y2:real;

Begin

Write (`Введите значение x:`);

ReadLn (x);

y1:=(exp(x)+exp(-x))/2;

y2:=(exp(x)-exp(-x))/2;

y:=sqrt(y1)-sqrt(y2);

WriteLn (`y1=`, y1:13:11)

WriteLn (`y2=`, y2:13:11)

WriteLn (`y=`, y:13:11)

End.

Последовательно вводя x = 5, 6, 7 ... 14, получаем, что y = 1, хотя погрешность результата растет. Однако при x = 15, y = 0 (!!!) Почему такое происходит? Сведем результаты при x = 0, 5, 10, 14, 15, и 20 в таблицу и расчитаем абсолютную и относительную погрешности результата.

xy1, y2y∆, b
0y1=1.00000000000 y2=0.000000000001.00000000000∆ = 0, b = 0%
5y1=74.2099485248 y2=74.20321057780.99999999999∆=0.0000000011 b=0.000000011%
10y1=11013.2329201 y2=11013.2328287471.00008608813∆=0.0008608813 b=0.008608813%
14y1=601302.142083 y2=601302.1420821.14689281583∆=0.14689281583 b=14.689281583%
15y1=1634508.68623 y2=1634508.686230.00000000000∆=1 b=100%
20y1=242582597.704 y2=242582597.7040.00000000000∆=1 b=100%

Из таблицы видно, что значения функций ch x и sh x с увеличением x быстро растут, а чем больше число, тем длинее запись мантиссы. Наконец, при x=15 разрядной сетки для записи мантиссы числа перестает хватать. При этом, младшие разряды мантиссы, которые различны для ch x и sh x отбрасываются, и при возведении чисел в квадрат мы получаем одинаковые результаты.

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

ch2x - sh2x = (chx - shx)(chx - shx),

в котором значения уменьшаемого и вычитаемого растут не так быстро.

Hosted by uCoz