Dan*_*udy -1 c algorithm math trigonometry
我正在使用Maclaurin系列用于arctan(x)而我得不到正确的答案.我正在用弧度进行计算.这是迄今为止的功能:
fp32 t32rArcTangent(fp32 number)
{
fp32 a, b, c, d; /* Temp Variables */
fp32 t; /* Number Temp */
uint32 i; /* Loop Counter */
/* Time Savers */
if (b32fpcomp(number, MM_FP8INFINITY)) return((fp32)MM_PI / 2);
if (b32fpcomp(number, -MM_FP8INFINITY)) return(-(fp32)MM_PI / 2);
/* Setup */
a = 0;
b = 0;
c = 1;
d = number;
t = number * number;
/* Calculation Loop */
for (i = 0; i < MMPRVT_FP32_TRIG_LIMIT; i++)
{
b += d;
if (b32fpcomp(a, b)) break;
a = b;
c += 2;
d *= -1 * t / c;
}
#ifdef DEBUG
printf("Loops: %lu\n", i);
#endif
/* Result */
return(a);
Run Code Online (Sandbox Code Playgroud)
fp32 = typedef'd float
uint32 = typedef'd unsigned long int
MM_FP8INFINITY是fp32数据类型可以包含的最大数字.
MM_PI只是PI大约50位数.
MMPRVT_FP32_TRIG_LIMIT是可用于计算结果的最大循环数.这是为了防止系列扩展进入无限循环,如果由于某种原因系列无法收敛.
这些是我得到的结果:
Testing arctangent(x) function.
Loops: 0
arctan(0): 0
Loops: 8
arctan(1): 0.724778414
Loops: 13
arctan(R3): 0.709577262
Loops: 6
arctan(1/R3): 0.517280579
Run Code Online (Sandbox Code Playgroud)
R3只是3的平方根,即1.732050808 ....
现在我知道arctan系列的收敛半径是| x | <= 1,所以我想我必须以某种方式减少输入.问题是对于arctan,函数的域是(-INF,+ INF).那你怎么减少呢?这是根据弧度计算的.
感谢您指出了这一点.问题已得到纠正,我也完成了输入减少.这是完成并更正的功能,现在给出了正确的答案:
fp32 t32rArcTangent(fp32 number)
{
fp32 a, b, c, d; /* Temp Variables */
fp32 t; /* Number Temp */
uint32 i; /* Loop Counter */
uint8 fr; /* Reduction Flag */
/* Time Savers */
if (b32isInf(number) == -1) return(-(fp32)MM_PI / 2);
if (b32isInf(number) == 1) return((fp32)MM_PI / 2);
if (b32isNaN(number)) return(number);
if (b32fpcomp(number, MM_FP8INFINITY)) return((fp32)MM_PI / 2);
if (b32fpcomp(number, -MM_FP8INFINITY)) return(-(fp32)MM_PI / 2);
if (b32fpcomp(number, ONE)) return((fp32)MM_PI / 4);
if (b32fpcomp(number, -ONE)) return(-(fp32)MM_PI / 4);
/* Reduce Input */
if (number > ONE)
{
number = 1 / number;
fr = 1;
}
else fr = 0;
/* Setup */
a = 0;
b = 0;
c = 1;
d = number;
t = number * number;
/* Calculation Loop */
for (i = 0; i < MMPRVT_FP32_TRIG_LIMIT; i++)
{
b += d / c;
if (b32fpcomp(a, b)) break;
a = b;
c += 2;
d *= -1 * t;
#ifdef DEBUG
printf("a=%g b=%g, c=%g d=%g\n", a, b, c, d);
#endif
}
#ifdef DEBUG
printf("Loops: %lu\n", i);
#endif
/* Result */
if (fr != 0) a = ((fp32)MM_PI / 2) - a;
return(a);
}
Run Code Online (Sandbox Code Playgroud)
考虑由于划分的结果,每个循环中的术语会发生什么c:
c += 2;
d *= -1 * t / c;
Run Code Online (Sandbox Code Playgroud)
首先,你除以1 [隐含地,在此之前],然后除以3,然后除以5,这听起来不错,但是因为你将d乘以这个术语,你实际上除以每个的乘积除数.IOW,而不是
x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + 1/9*x^9
Run Code Online (Sandbox Code Playgroud)
你想要的,你在计算
x - 1/(1*3)*x^3 + 1/(1*3*5)*x^5 - 1/(1*3*5*7)*x^7 + 1/(1*3*5*7*9)*x^9
Run Code Online (Sandbox Code Playgroud)
你仍然可以使用你的d *= -t技巧,但你应该移动该部门.