Современное программирование предлагает пользователям использовать самые разнообразные языки программирования. Но основой основ является Паскаль.Данный язык был разработан в 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 в таблицу и расчитаем абсолютную и относительную погрешности результата.
Из таблицы видно, что значения функций ch x и sh x с увеличением x быстро растут, а чем больше число, тем длинее запись мантиссы. Наконец, при x=15 разрядной сетки для записи мантиссы числа перестает хватать. При этом, младшие разряды мантиссы, которые различны для ch x и sh x отбрасываются, и при возведении чисел в квадрат мы получаем одинаковые результаты. Для избежания подобных случаев, в каждом конкретном случае используют разные приемы. Например, в данном примере можно использовать типы данных с большим количеством значащих цифр или вычислять преобразованное выражение: ch2x - sh2x = (chx - shx)(chx - shx), в котором значения уменьшаемого и вычитаемого растут не так быстро. |
---|