Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 июня!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



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

Алгоритм вычисления арктангенса

(добавлены арксинус и арккосинус)

Арктангенс вычисляется методом сужения области определения до [0,pi/12] и аппроксимации в этой области. Алгоритм оптимизирован для single precision floating point.

Арксинус легко вычисляется через арктангенс (с дополнительным использованием вычисления квадратного корня), а арккосинус - через арксинус.
Для вычисления арктангенса использован следующий алгоритм:
Вначале проверить знак x, изменить знак, сделав аргумент неотрицательным.
Затем если x>1, обратить его: x1=1/x.
Затем сокращаем область определения, используя формулу:

atan(x)=pi/6+atan((x*sqrt(3)-1)/(x+sqrt(3))).
Здесь sqrt(3) квадратный корень из 3. При этом необходимо запомнить число шагов (возможно, ноль).
После этого, арктангенс на интервале [0,pi/12] аппроксимируется формулой (для single precision, в случае double формула должна быть улучшена!):
atan(x) = x*(0.55913709/(1.4087812+x2) +0.60310579-0.05160454*x2)
Затем к полученному результату добавляется столько pi/6, сколько было шагов сокращения области определения. Затем, в случае обращения, аргумента, результат вычитается из pi/2. Затем, если была смена знака, у результата меняем знак.

Для повышенной точности, формулу на участке [0,pi/12] следует брать в виде:
atan(x) = x*(m0+n0*(x*x)+k0/(m1+n1*(x*x)+k1/(m2+n2*(x*x)+k2/(...)))),
то есть в том же виде цепной дроби, как и для single precision, только с некоторыми другими значениями m0,n0,k0;m1,n1,k1;... Определению подобных значений будет посвящена задача, представляющая из себя частный случай алгоритма минимизации функции нескольких переменных.

Для вычисления арксинуса следует воспользоваться соотношением:
asin(x)=atan(x/sqrt(1-x2)),   где sqrt(x) - квадратный корень.
Арккосинус связан с арксинусом соотношением acos(x)=pi/2-asin(x). Для его вычисления следует сначала воспользоваться вычислением арксинуса. Для обоих случаев необходимо отслеживать случаи x=1, x=-1 (где требуется находить арктангенс бесконечности), а также случаи выхода x из области определения, где следует генерировать ошибку. В программе arcsin.c, приведенной ниже, используются литералы NORMAL для указания нормальной работы и EDOM для завершения с ошибкой.

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

 
 /* arctangent computation without math lab */
 
    Copyright © Nikitin V.F. 2000
 
 
 
    float Arctan(float x); - the usage is clear
 
 */
 
 
 
 #define M_PI ((float)3.141592653589793)
 
 #define M_PI12 (M_PI/12.F)
 
 #define M_PI6 (M_PI/6.F)
 
 #define M_PI2 (M_PI/2.F)
 
 /* square root of 3 */
 
 #define SQRT3 ((float)1.732050807569)
 
 
 
 float Arctan(float x) {
 
   int sta=0,sp=0;
 
   float x2,a;
 
   /* check up the sign change */
 
   if(x<0.F) {x=-x;sta|=1;}
 
   /* check up the invertation */
 
   if(x>1.F) {x=1.F/x;sta|=2;}
 
   /* process shrinking the domain until x<PI/12 */
 
   while(x>M_PI12) {
 
     sp++; a=x+SQRT3; a=1.F/a; x*=SQRT3; x-=1.F; x*=a;
 
   }
 
   /* calculation core */
 
   x2=x*x; a=x2+1.4087812F; a=0.55913709F/a; a+=0.60310579F;
 
   a-=0.05160454F*x2; a*=x;
 
   /* process until sp=0 */
 
   while(sp>0) {a+=M_PI6;sp--;}
 
   /* invertation took place */
 
   if(sta&2) a=M_PI2-a;
 
   /* sign change took place */
 
   if(sta&1) a=-a;
 
   return(a);
 
 }
 
 


 
 /* Arcsine and arccosine calculation. Uses Arctan() and Sqroot() as
 
    external calls.
 
 
 
    int Arcsin(float *a,float x);
 
        x - argument,
 
        a - pointer to result
 
    Returns error code NORMAL or EDOM
 
 
 
    int Arccos(float *a,float x);
 
        x - argument,
 
        a - pointer to result
 
    Returns error code NORMAL or EDOM
 
 
 
 */
 
 
 
 #define M_PI ((float)3.141592653589793)
 
 #define M_PI2 (M_PI/2.F)
 
 
 
 enum{NORMAL,EDOM};
 
 
 
 extern float Arctan(float x);
 
 extern float Sqroot(float x);
 
 
 
 int Arcsin(float *a,float x) {
 
  /* check for exceptions */
 
  if(x<-1.F) {*a=-M_PI2;return(EDOM);}
 
  if(x==-1.F) {*a=-M_PI2;return(NORMAL);}
 
  if(x>1.F) {*a=M_PI2;return(EDOM);}
 
  if(x==1.F) {*a=M_PI2;return(NORMAL);}
 
  /* transform the argument */
 
  x/=Sqroot(1.F-x*x);
 
  *a=Arctan(x);
 
  return(NORMAL);
 
 }
 
 
 
 int Arccos(float *a,float x) {
 
  int re=Arcsin(a,x);
 
  *a=M_PI2-(*a);
 
  return(re);
 
 }
 
 

Скачать файлы arctan.c и arcsin.c


<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS