Разложение в ряд Маклорена:
y = arctg(x) = x - x^3/3 + x^5/5 - ... |x| < 1
arctg(1/x) = 1/x - (1/2)x3 + (1/5)x5 - .
tan(x) = x/(1-x^2/(3-x^2/(5-x^2/(7-x^2/...))))
Пусть max - больший катет, а min - меньший. Тогда длина гипотенузы приблизительно равна
Еще один пример ряда для x < 1;
Еще одна эмпирически подобранная формула:
y = arctg(x) = x - x^3/3 + x^5/5 - ... |x| < 1
arctg(1/x) = 1/x - (1/2)x3 + (1/5)x5 - .
tan(x) = x/(1-x^2/(3-x^2/(5-x^2/(7-x^2/...))))
Пусть max - больший катет, а min - меньший. Тогда длина гипотенузы приблизительно равна
max + min*min/(2*max)
Её максимальная относительная ошибка равна: 1 - sqrt(2)/1.5 ~ 0.057
А если взять формулу:
max + 0.43*min*min/max, то максимальная относительная ошибка будет ~ 0.01
Если же хочется сделать вычисления проще, то можно взять формулу:
max + 0.41*min, но ошибка будет 0.075
Коэффициенты подобраны экспериментально с точность 0.01. Можно подобрать точнее.Еще один пример ряда для x < 1;
Еще одна эмпирически подобранная формула:
//formula y = -0.30097 + 0.61955*x - 0.001659*x*x
//x :number from 0..100%
//y : angle from 0..45° as approximation of the atan function.
int32_t arctang(int32_t Re, int32_t Im)
{
int32_t a,b,proc,arctg;
proc=a*100.0/b;
//proc_int=a*100/b;
arctg=(-300970 + 619550*proc - 1659*proc*proc)/1000000;
return arctg;
}
Для вычисления арктангенса можно использовать следующий алгоритм:
Вначале проверить знак 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;...
#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);
}
Комментариев нет:
Отправить комментарий