Info Guide #08
30 ноября 2005

For Coderz - Вычисление тригонометрических и алгебраических функций в языках высокого уровня.

<b>For Coderz</b> - Вычисление тригонометрических и алгебраических функций в языках высокого уровня.
               Смирнов В.В.

      Вычисление тригонометрических
          и алгебраических функций
   (SIN, COS, TAN, ATAN, LOG, EXP, ...)
         в языках высокого уровня

   Все эти функции в БЕЙСИКЕ именуют "ста─
ндартными"  или "встроенными". В ФОРТРАНЕ,
ПАСКАЛЕ  и в др. языках  высокого уровня -
"стандартными" или "библиотечными".
   Для  разработки  алгоритмов  вычисления
этих функций всюду,в т.ч. в микрокалькуля─
торах,применена тема т.н. "рядов".Ряд есть
сумма бесконечного числа слагаемых. Напри─
мер, для функции sin (x) ряд является зна─
копеременным, по нечётным степеням аргуме─
нта (аргумент в радианах):

 sin(x)=x-x^3/3!+x^5/5!-x^7/7!+x^9/9!- ... 
   ... +(-1)^n*x^(2*n+1)/(2*n+1)!+ ...
  
   Для некоторых других функций ряды пред─
ставляются такими:
 

     cos(x)=1-x^2/2!+x^4/4!-x^6/6!+ ...
     ... +(-1)^n*x^(2*n)/(2*n)!+ ...
т.е.знакопеременный ряд по чётным степеням
аргумента;
 

   e^x = 1+x/1!+x^2/2!+x^3/3!+x^4/4!+ ...
             ... +x^n/n!+ ...

         обозначив (x-1)/(x+1)=z,
           запишем следующий ряд:
     ln(x)=2(z+z^3/3+z^5/5+z^7/7+z^9/9+ ...
       ... +z^(2*n+1)/(2*n+1)+ ...
    
   arcsin(x)=x+x^3/(2*3)+1*3*x^5/(2*4*5)+
         +1*3*5*x^7/(2*4*6*7)+ ...
     ... +(1*3*5*...*(2*n-1)*x^(2*n+1)/
      (2*4*6*...*(2*n)*(2*n+1))+...
 

   (Ряды некоторых функций,например,танге─
нса и секанса, содержат в качестве коэффи─ 
циентов  специальные  числа (здесь - числа 
Бернулли  и числа  Эйлера соответственно). 
Для  вычисления этих чисел потребуется со─ 
ответствующий алгоритм,который станет,сле─ 
довательно,частью алгоритма вычисления ря─ 
да соответствующей функции.) 

   Эти представления рядов различных функ─
ций приводятся в математических справочни─
ках, в математических словарях,в математи─
ческой энциклопедии.
   Исходно  ряды  получают  и  исследуют в
вузовских  курсах  математического анализа
(иначе - курс дифференциального и интегра─
льного исчисления), в состав которых (кур─
сов) тематика "рядов" входит  в обязатель─
ном  порядке - можете поискать в вузовских
многочисленных томах "матана".В "рядах" из
справочников  следует иметь в виду для да─
льнейшего, что  приводимое в них выражение
т.н."общего члена ряда" (позволяющее полу─
чить по номеру слагаемого  выражение этого
слагаемого) может  начинаться  как с нуля,
так  и с единицы - по выбору  составителей
справочника. Этот  начальный номер следует
уточнить,в конкретном случае подставив n=1
и оценив, получается ли в полном представ─
лении  первый член ряда, или же второй. (В
последнем случае, следовательно,номера на─
чинаются от нуля.)
   
   При вычислении этих "стандартных" функ─
ций  широко используется функция "фактори─
ал",обозначаемая "восклицательным знаком".
Напомним здесь:целочисленная функция цело─
численного  аргумента, "эн факториал" (n!)
означает  произведение всех целых чисел от
 1 до n. 
   (Ред.: 0! принято равным 1. Для дробно─
го аргумента  факториал можно доопределить 
через гамма-функцию.) 

   Итак, о вычислении тригонометрических и
алгебраических функций.
   Для  практической реализации алгоритма,
очевидно, следует  вычислить и просуммиро─
вать некоторое КОНЕЧНОЕ КОЛИЧЕСТВО СЛАГАЕ─
МЫХ - ЧЛЕНОВ РЯДА.Для построения алгоритма
вычисления, скажем,синуса следует задаться
точностью  вычислений - допустим, 0.00001.
Это значение  будет использовано в единст─
венном в программе операторе условного пе─
рехода:когда очередное слагаемое по модулю
станет  меньше заданной точности (перемен─
ная Т ),следует прекратить накопление сум─
мы и перейти к печати результата.
   В алгоритме  сначала назначаем перемен─
ные, используемые  в  программе: X - аргу─
мент; N - текущее значение показателя сте─
пени (и аргумента  факториала);  S - пере─
менная, в которой накапливается сумма и, в
конечном итоге,в которой оказывается вычи─
сленное значение синуса (соответственно, С
- переменная  суммирования  косинуса); H -
очередное слагаемое для суммирования.
   Алгоритм может быть построен с вычисле─
нием  очередного  члена ряда (слагаемого):
как по полной формуле "общего члена ряда",
так и с использованием для вычислений оче─
редного  слагаемого, результата вычислений
предыдущего слагаемого (т.е. с переопреде─
лением  переменной, где  новое её значение
определяется  через старое значение). Этот
второй путь лучше,проще,короче,т.к.не при─
ходится отдельно вычислять функцию "факто─
риал". Кроме  того, второй способ, видимо,
короче по времени. А самое главное, прямой
метод  может  отказать из-за переполнения,
т.к. факториал растёт даже быстрее,чем по─
казательная функция.
   
   Вот  полный алгоритм вычисления функции
"синус":

 (А) 
     10 LET X=1.2345
     20 LET T=0.00001
     30 LET N=1
     40 LET S=X
     50 LET H=X
     60 LET H=H*(-1)*X^2/(N+1)/(N+2)
     70 LET S=S+H
     80 LET N=N+2
     90 IF ABS(H)>T THEN GOTO 60
   100 PRINT "S=";S

   В строках 10 - 50 задаём начальные зна─
чения  соответствующих переменных. (Вообще
накопление  суммы чаще начинают с нуля, но
здесь удобнее с первого члена ряда,с исхо─
дного X ).
   В строке 60  происходит вычисление оче─
редного  члена  ряда  с использованием его
"старого" значения. "Старое" - это выраже─
ние предыдущего члена ряда. Формула строки
60  получена  за счет сравнения ДВУХ ЛЮБЫХ 
СОСЕДНИХ членов ряда. Скажем, 2-го и 3-го.
Чем  они отличаются? На "икс в квадрате" -
в числителе, на два новых следующих поряд─
ковых числа - в знаменателе,а также знаком
"плюс-минус". Всё это  и отражено в строке
60. 
   В строке 70  происходит накопление сум─
мы, т.е. "главное вычисление". В строке 80
вычисляется новое значение параметра N для
последующих членов ряда,если они будут вы─
числяться.
   В строке 90 как раз определяется: "пре─
кратить вычисления", или "продолжать",если
точность ещё не достигнута.

   Программа вычислений по первому вариан─
ту (с использованием выражения общего чле─
на ряда) дана ниже:

 (В) 
     10 LET X=1.23456
     20 LET N=1
     30 LET T=0.00001
     40 LET S=0
     50 LET A=1
     60 LET F=1
     70 FOR K=1 TO (2*N+1):LET F=F*K:NEXT K
     80 LET H=A*X^(2*N+1)/F
     90 LET S=S+H
    100 LET A=-A
    110 LET N=N+1
    120 IF ABS(H)>T THEN GOTO 60
   130 PRINT "S=";S

   Здесь в строках 60, 70 вычисляется фун─
кция  "факториал": в  цикле  накапливается
произведение  чисел от единицы до текущего
параметра.Использование переменной A - это
"ухищрения"  в связи  с тем, что нужное по
формуле общего члена ряда вычисление "зна─
коизменяющего" сомножителя ПРИ ПЕРВОМ ПРО─
ХОДЕ, для  "минус единицы в степени нуль",
может происходить НЕВЕРНО (или с сообщени─
ем об ошибке) на разных машинах и в разных
версиях Бейсика.Нужно отметить,что показа─
тельная функция с отрицательным основанием
не  определена. Видим, что  эта  программа
более громоздка,чем предыдущая. К тому же,
имеет  недостатки, названные выше. Поэтому
с этим типом программ (В) далее не работа─
ем.

                  * * *

   Если  бы  в программе (А) потребовалась
выдача значений функций для аргумента,вво─
димого  с клавиатуры  ("справочник  Бради─
са"), то в строке 10 вместо назначения ар─
гумента будет оператор INPUT.
   Или, скажем,вместо вывода на печать ре─
зультат может быть передан другой програм─
ме, а эта станет, т.о.,подпрограммой - для
тех  версий Бейсика или другого языка, где
исходно  нет  тригонометрии,  например,  в
"Бейсик-микро"  (ж. "Радио",  1980-е гг.), 
либо  в каком-нибудь /разработанном вами!/
простейшем языке высокого уровня. В "само─
пальном" ЯВУ  этот путь позволяет получить
тригонометрию  более  простыми  средствами
самого же языка, а не более трудоёмкой ма─
шиннокодовой  процедурой. Это экономит па─
мять (ПЗУ), но,например,ведёт к потерям во
времени.
   
   Для вычисления значений  функции "коси─
нус" нетрудно  составить аналогичную прог─
рамму. Если же нужно иметь и синус,и коси─
нус, можно  доработать исходную программу,
добавив в (А) следующие строки:
 

     45 LET C=1
     75 LET C=C+H/X*(N+2)
   120 PRINT "C=";C

   Здесь  в строке 45 назначается перемен─
ная  С, в которой будет накапливаться зна─
чение ряда косинуса. Этой переменной прис─
воено, соответственно, начальное  значение
ряда косинуса.
   Единственная  строка  вычислений  здесь
(75) использует вычисленное к этому момен─ 
ту значение  очередного (с тем же порядко─
вым  номером)  члена  ряда  синуса. В этой
строке  происходит накопление ряда косину─
са, с откорректированным значением H. (Пе─
ременная H этой строкой не меняется.) Кор─
рекция  заключается в домножении на множи─
тель  (N+2)/X. Вид  множителя  получен  из
сравнения "одноимённых" членов ряда синуса
и косинуса.

   Обычно  при практической реализации вы─
числений, используя периодичность тригоно─
метрических  функций, пересчитывают  аргу─
мент,вычитая целое число периодов (кратное
2*пи=6.283185307179586476925286766559...). 
Иначе  ряд "хуже сходится", т.е. требуется
гораздо большее число итераций (см. ниже).
Кроме того,в таких же целях аргумент после
этого  ещё уменьшают: используя "школьные"
формулы приведения,приводят в первый квад─
рант. Тогда вычисления очень коротки.

                  * * *
   
   Далее,развивая и изменяя программу (А),
проведём небольшое исследование. (Дальней─
шее имеет общих характер для численных ме─
тодов.Т.е.приложимо не только к вычислению
стандартных функций ЯВУ.)
   Любая задача, после её решения, требует
ПРОВЕРКИ.
   Здесь  можно  выполнить  проверку двумя
 способами:
  а) можно вычислять  известные функции от
известных  аргументов, например, синус  от 
 пи/6; 
  б) вычисляя "встроенными" функциями SIN,
COS, ... которые, конечно, имеются во всех 
современных версиях ЯВУ. 

   Для  проверки  по  второму способу надо
 добавить строку:
    110 PRINT "SIN=";SIN(X)
   При этом полезно подкорректировать фор─
мат вывода  предыдущей строки (100), чтобы
удобно было сравнивать одноимённые разряды
(там - добавить 2 пробела внутри кавычек).

    Далее. Добавим в (А) строку: 
     78 PRINT S;" ";C;" ";H
   В результате того,что эта печать задана
НА ПОВТОРЯЮЩЕМСЯ УЧАСТКЕ ПРОГРАММЫ, в про─
цессе решения машина напечатает в три сто─
лбца текущие значения названых переменных.
По этим данным  можно видеть, как происхо─
дило приближение к настоящему значению си─
нуса  (косинуса). (Настоящее - вычисленное
встроенной соответствующей функцией.) Так─
же видно  уменьшение модуля H до значения,
ниже  заданного  в  Т. Причём  меньшее Т -
единственная строка перед печатью итогово─
го результата.Из этих трёх столбцов следу─
ет и ещё кое-какая информация: СКОЛЬКО РАЗ
машина прошла на этом повторяющемся участ─
ке программы.А именно:сколько строк - сто─
лько и повторений.
   
   Для оценки  количества проходов по пов─
торяющемуся  участку  программы  обычно на
циклическом её участке добавляют счётчик:
 

     23 LET K=0
     65 LET K=K+1
   133 PRINT "K=";K

   Изменяя  требуемую точность  -  задавая
0.0001 или 0.000001 - будем  получать раз─ 
ное число строк в столбцах.Чем больше точ─
ность, тем, очевидно,больше число проходов
(итераций), и соответственно, больше пара─
метр К  и больше число строк вспомогатель─
ной печати (здесь - переменных S,C,H внут─
ри цикла).
   
   Далее. Скажем, при  точности  "десять в
минус пятой" в итоговых результатах совпа─
дут  (со встроенной функцией) по пять цифр
после запятой (Ред.: вернее сказать, резу─
льтаты  будут отличаться  не больше чем на 
единицу  5-го  разряда после запятой. Ниже 
аналогично). 
   При  точности "десять в минус шестой" -
совпадут по шесть цифр.
   Если назначить точность "десять в минус
восьмой", то совпадут все  цифры, и, таким
образом, результат по этому алгоритму ока─
зывается в точности тем же,что и по встро─
енным функциям SIN(X), COS(X).
   Стало  быть, своей программой вы можете
превзойти точность вашей версии языка: до─
пустим,если в нем не заложена "двойная то─
чность" (16 значащих цифр) - задайте  дос─
таточно малое значение Т.
   
   Если  задать  значения  аргумента более
"пи/2" или ещё более - "Х+2*пи", - то мож─
но видеть,как резко замедляется сходимость
ряда.Причём сначала появляются сильные ко─
лебания модуля суммы.Из всего этого и сле─
дует  целесообразность пересчёта аргумента
в первый квадрант.

SWW (A.E.-2) 



Другие статьи номера:

Inferno - Авторы журнала.

Inferno - Вступление от редактора.

Inferno - Ошибки в предыдущих номерах.

Inferno - Об оболочке.

Железо - CD-ROM - устройство и хитрости подключения.

For Coderz - CD video на ZX. Как написать плеер видео с компакт-диска.

Sofтинка - Техническое руководство по дисковой системе DISCiPLE/+D.

For Coderz - Маленькие программерские хитрости.

Математика - История решения теоремы Ферма.

Gameland - Игра Шестнашки.

Sofтинка - Описания и история изменений программы для работы с жестким диском HDDoctor v0.9.

Секреты - Секретные кнопки в разных приложениях: Wolfenstein'2004, IG#5, ACEdit, DNA OS, Wild Disk Copier.

Sofтинка - Улучшения конвертора графики в Gigascreen.

Звук - Ламповые усилители. Стерео лампочник 2х5 Вт из старых телевизоров.

Железо - Обзор кассетных проигрывателей.

Inferno - Письма в редакцию.

Gamedev - История создания игры Pang.

Gamedev - Советы при написании аркадной игры.

Реклама - Реклама от Романа Чунина.

Реклама - Реклама от Алексея Жабина.

Реклама - Реклама от В. Богдановича.

Интервью - Интервью с Николаем Родионовым, автором известных книг для ZX Spectrum

For Coderz - Вычисление тригонометрических и алгебраических функций в языках высокого уровня.

DIY - схема 16-цветного видео-режим v1.1 для пентагона.

Железо - Описание микросхемы К555ТЛ2.

For Coderz - Программирование устройства генерации звука Turbo Sound.

Sofтинка - 384x304 viewer. программа позволяющая просматривать цветные картинки, по размерам превышающие экран.

Sofтинка - Эмулятор ZX Spectrum на ZX Spectrum.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Горячий привет - крах оригинального проекта "ELITE-3". Рассказ о скандальной истории, связанной с этой игрой.
Юмор - Анекдоты про Штирлица.
Реклама - Реклама и обьявления.
Информация - Чёрный ящик
Экспертиза - игра "Swords & Sorcery". Это предшественница популярных ролевых игр приятно удивит Вас обширным игровым пространством, обилием монстров, чудовищ и колдунов.

В этот день...   21 ноября