Надеюсь, вы уже обратили внимание, уважаемый подписчик, что возможности Паскаля мы с вами изучаем постепенно, по мере возникновения потребности в них для решения тех или иных задач. Продолжаем!
Сегодня мы рассмотрим несколько специальных математических функций Паскаля, существенно влияющих на качество решения задач. Субъектом их применения будут всё те же простейшие линейные подпрограммы с результатами числового типа.
ПРИМЕНЕНИЕ ФУНКЦИЙ ПРЕОБРАЗОВАНИЯ АРГУМЕНТА
1. Математические функции преобразования аргумента.
К математическим функциям преобразования аргумента относятся следующие:
1). Функция преобразования Round(X: Real): LongInt применяется к выражению X вещественного типа. В результате получится округлённое значение, имеющее целый тип. Округление выполняется до ближайшего целого числа. Если X находится точно посередине между двумя целыми числами, то результатом будет число с большим абсолютным
значением. В случае его выхода за пределы типа LongInt будет получено сообщение об ошибке.
2). Функция преобразования Trunc(X: Real): LongInt применяется к выражению X вещественного типа. В результате отбрасывания дробной части получится значение, имеющее целый тип. В случае его выхода за пределы типа LongInt будет получено сообщение об ошибке.
3). Функция преобразования Frac(X: Real): Real применяется к выражению X вещественного типа. В результате получится дробная часть аргумента, имеющая вещественный тип.
4). Функция преобразования Int(X: Real): Real применяется к выражению X
вещественного типа. В результате отбрасывания дробной части получится целая часть аргумента, имеющая вещественный тип.
2. Решение задачи “Угол ® Секунды”.
Задача L.3.4. “Угол®Секунды”. Известно, что одна из стрелок часов делает полный оборот за D полных секунд. От начала суток эта стрелка повернулась на угол Aрадиан.Построить алгоритм и подпрограмму вычисления количества полных секунд, которые прошли от начала суток.
На вопрос задачи ответить легко, если известно, за сколько секунд данная стрелка поворачивается на один радиан. Ответ получим, умножив эту величину на количество радиан A поворота стрелки.
Вполне очевидно, что нужная продолжительность поворота на один радиан может быть определена путём деления продолжительности полного оборота D в секундах на угол полного оборота, равный 2*π радиан.
Таким образом, продолжительность поворота на угол A радиан, выраженная в секундах, должна вычисляться с помощью выражения D/(2*π)*A.
Тип аргумента D может быть выбран натуральным, учитывая его смысл (количество полных секунд полного оборота стрелки), а также исходя из естественного ограничения D > 0. Тип аргумента A, исходя из его смысла (угол поворота стрелки в радианах), должен быть выбран вещественным. При этом допустимы значения A 0. Таким образом, выражение D/(2*π)*A имеет вещественный
тип сразу по двум причинам (вещественный тип A и наличие операции деления “/”).
Теперь учтём, что условие задачи требует получения целочисленного значения количества полных секунд, прошедших от начала суток. Для этого необходимо в полученном значении отбросить дробную часть и преобразовать его к целому типу. Этогоможно добиться применением функции Trunc.
Алгоритм и его перевод на Паскаль выглядят следующим образом:
алг Угол_Сек ( A: вещ, D: нат ): нат дано угол
A и длительность оборота D надо число полных секунд на угол A нач Угол_Сек := Trunc ( D
/ ( 2 * π ) * A ) кон
Function Ang_Sec(A:Real; D:LongInt):LongInt; Begin Ang_Sec := Trunc ( D / ( 2*Pi) * A ) End;
При обращении к алгоритму реальными фактическими значениями параметра D могут быть 60 секунд для секундной стрелки, 3600 секунд для минутной стрелки и 3600 *
3. Решение задачи “Косинус угла”.
Задача L.1.6. “Косинус угла”. Заданы стороны треугольника a, b, c. Построить алгоритм и подпрограмму вычисления косинуса угла A, лежащего против стороны a.
Для решения этой задачи можно воспользоваться известной теоремой косинусов, являющейся обобщением теоремы Пифагора: квадрат любой стороны треугольника (a) равен сумме квадратов двух других его сторон (bи c)
без удвоенного произведения этих сторон на косинус угла (A) между ними, то есть a2= b2+ c2–2*b*c*cosA.
Решение задачи выполним в два шага: сначала найдём числитель x = b2+ c2– a2, а затем и нужный cosA = x / (2*b*c).
Такой порядок вычислений выбран в связи с тем, что мы собираемся предварительно проконтролировать значение выражения b*b+c*c–a*a. При этом исходными данными для нас будут стороны прямоугольного треугольника: гипотенуза a = 5 мм и катеты b = 4 мм, c = 3 мм.
Вычислять будем с помощью одного из средств отладки программ ИСП – диалогового окна оперативного контроля и модификации значений переменных Evaluate and Modify. Это окно можно открыть, нажав клавиши <Ctrl + F4> после запуска ИСП. Им можно пользоваться как обычным калькулятором. Однако, преимущества этого окна состоят в том, что оно даёт те же значения результатов вычислений, что и соответствующие программы на Паскале. Вводите
выражение в поле Expression, нажимайте клавишу <Enter> и получайте результат вычислений в поле Result. А чтобы правильно прочитать число, появляющееся в поле результата, полезно предварительно ознакомиться с правилами записи вещественных десятичных чисел в показательной форме (http://a-morgun.narod.ru/a08-01/a0008-0001-0001-0003.html).
Результаты вычислений для одного и того же прямоугольного треугольника, стороны которого измеряются в разных единицах длины, сведены в таблицу:
№
a
b
c
Единица измерения
b*b+c*c–a*a
1
5
4
3
мм
0
2
0.5
0.4
0.3
см
2.7105054312E–20
3
0.005
0.004
0.003
м
–1.6543612251E–24
В первом случае получаем абсолютно точный результат. Значение указанного выражения равно нулю, что соответствует прямому углу 90˚.
Во втором случае получаем очень маленькое положительное число. Значение указанного выражения соответствует некоторому острому углу, близкому к 90˚.
В третьем случае получаем близкое к нулю отрицательное число. Теперь значение указанного выражения соответствует некоторому тупому углу, близкому к 90˚.
Последние два случая демонстрируют отличия значений выражения от нуля, возникающие по причине приближённого характера машинных вычислений. Эти отличия весьма незначительны, но даже они могут привести к серьёзным качественным ошибкам, например, при выяснении того, является ли данный треугольник прямоугольным.
Отличия значений от нуля возникают в последних разрядах. Эти последние цифры считаются неправильными и называются “мусором”. Чтобы обеспечить правильный результат, от “мусора”, возникающего в последних разрядах числа, следует избавляться.
Методику уборки “мусора” разберём на примере. Пусть x = 2.5001. Договоримся считать “мусором” всё то, что находится далее третьего разряда после десятичной точки. Умножим x на 103 = 1000, получим
x = 2500.1. Отбросим дробную часть: x = 2500. Вернёмся к исходному состоянию, разделив x на 1000. Получим x = 2.5. “Мусор” убран.
Теперь предположим, что “замусоренным” является нулевое значение. Тот же метод позволяет сделать его “чистым”. Пусть x = 0.0001. Договоримся считать нулями все числа, абсолютная величина которых меньше 0.001 = 10–3. Умножим x на 103 = 1000, получим
x = 0.1. Отбросим дробную часть: x = 0. Возврат к исходному состоянию путём деления x на 1000 ничего не меняет. Нужный нам чистый нуль x = 0 получен.
Остаётся договориться о том, что считать “мусором”. Как правило, это должно зависеть от конкретных условий решения той или иной задачи. Например, в нашей задаче вычисления косинуса угла договоримся считать “мусором” всё то, что находится далее десятого разряда после десятичной точки. Соответственно можно считать нулевыми все значения, абсолютная величина которых меньше
10–10. В этом случае избавляться от “мусора” и “очищать” нули можно с помощью выражения Int(x*1E10)/1E10, в котором функция преобразования Int отбрасывает дробную часть своего аргумента.
Разумеется, предложенный метод “уборки мусора” не гарантирует качественного результата во всех случаях. Однако, вероятность его получения стала более высокой.
Общая рекомендация состоит в том, что “уборка мусора” бывает полезна тогда, когда предполагается получать результат вычитания близких по значению величин вещественного типа. Это согласуется с известным выводом теории погрешностей о потере точности при вычитании близких величин.
Алгоритм и его перевод на Паскаль выглядят следующим образом:
алгCosineA ( a, b, c: вещ ): вещ начx: вещ x := b * b + c * c – a * a; x := Int ( x * 1E10) / 1E10; CosineA
:= x / ( 2 * b * c ) кон
Function CosineA ( a, b, c: Real ): Real; Var x: Real; Begin x := b * b + c * c – a * a; x := Int ( x * 1E10 ) / 1E10 CosineA := x / ( 2 * b * c) End;
В алгоритме и в подпрограмме CosineAпредварительно вычисленный числитель xс помощью оператора x := Int(x*1E10)/1E10 очищается от “мусора”. Если x должен быть равен нулю, то этим самым нуль будет получен “чистым”. Благодаря этому во всех рассмотренных примерах значения косинуса угла принимают точные нулевые значения.
Подчеркнём, что функция CosineA в соответствии с условием задачи предназначена для вычисления косинуса угла A, лежащего против стороны a. В перечне аргументов функции сторона aуказана на первом месте. Легко сообразить, что если в обращении к функции указывать на первом месте разные стороны треугольника, то можно получать и косинусы разных углов. Иначе
говоря, функция CosineA вычисляет косинус угла, лежащего против стороны, указанной первой в перечне сторон при обращении к ней.
И последнее. В функции CosineA в качестве аргументов используются стороны треугольника, на что прямо указано в условии задачи. Из этого следует, что значения переменных a, b, c предполагаются таким, что могут и должны быть сторонами треугольника. Если же это требование игнорировать, то функция CosineA
может оказаться нерезультативной. Например, при задании значений сторон нулевыми вычисления не могут быть выполненными из-за возникающего деления на нуль. А при задании невозможных для треугольника сторон a=2, b=3, c=6 функция даёт значение косинуса угла, превыщающее единицу.
Таким образом, мы с вами, уважаемый подписчик, сделали определённые шаги в направлении составления качественных, работоспособных программ. Для этого нам понадобились функции Паскаля, которые совсем не относятся к числу популярных. Попутно мы освоили незнакомые ранее полезные возможности ИСП.
Уважаемый подписчик!При необходимости задать вопрос, проконсультироваться, уточнить или обсудить что-либо обращайтесь через Гостевую книгу моего персонального сайта http://a-morgun.narod.ru
С уважением, Александр.
12 = 43200 секунд для часовой стрелки. Но чисто формально ничто не запрещает использовать для параметра D любое иное отличное от нуля значение. Конечно, при этом следует понимать, что никаким реально существующим часам это значение соответствовать не будет.