三角自变量约简(模2π的约简) [英] Trigonometric argument reduction (reduction modulo 2π)
问题描述
我正在尝试为正弦和余弦创建一个计算器,该计算器在技术上仅在0-pi/2的范围内运行.现在看来这很愚蠢,但以后会用到,所以我可以采用泰勒级数.
I am trying to create a calculator for sin and cosine that technically only operates on the range of 0-pi/2. Right now this might seem silly but later on it will be used so I can employ Taylor series.
我有一个最有效的实现,但是当theta的形式为x *(pi/2)时,我遇到了一个严重的问题,其中x是任意整数.似乎在这些值上有时会将它们推入它们不属于的附近象限.还有一些偶然的完全错误,我无法解释.
I have a mostly working implementation however I have a serious issue when theta is in the form of x * (pi/2) where x is an arbitrary integer. It would appear that on these values that sometimes they are pushed into a nearby quadrants they dont belong to. There are also some occasional outright errors that I cannot explain.
我该如何提高效率和正确性?
How can I shore this up making it more efficient and correct?
这是执行此操作的代码.
Here is the code for doing this.
#define T_PI (2.0 * M_PI)
#define H_PI (0.5 * M_PI)
void sincos(float theta, float* cosine, float* cosine) {
int mode;
prepareForRange(&theta, cosine, sine);
Assert(!(f < 0.0 || f > H_PI));
*cosine = cos(theta);
*sine = sin(theta);
range_output(mode, cosine, sine);
}
void prepareForRange(float* theta, int* mode, float *cosine, float* sine) {
if (*theta < 0.0) *theta += ceil(-*theta / T_PI) * T_PI;
*mode = (int)floor(*theta / H_PI) % 4 + 1;
*theta = fmodf(*theta, H_PI);
}
void range_output(int mode, float *cos, float *sin) {
float temp;
switch (mode) {
case 1:
break;
case 2:
temp = *cos;
*cos = -*sin;
*sin = temp;
break;
case 3:
*cos = -*cos;
*sin = -*sin;
break;
case 4:
temp = *cos;
*cos = *sin;
*sin = -temp;
break;
default:
break;
}
}
推荐答案
您遇到了一个长期存在且经常无法识别的问题区域,称为数字库中真正解决此问题,我必须有效地实现任意精度浮点算法,并存储一个320位(1078位)的PI常数.libc的某些实现为您有效地做到了这一点,但并非全部实现,因此您不能放心地假设它.
You are running into a long-standing and often-unrecognized problem area called range reduction. The basic problem is that a float PI constant is only defined 8 digit accuracy, so by the time you are trying to compute (x - n * PI) for n ~ 10^4, you have lost half the digits of accuracy in your results, and worse as n gets larger. There is no simple software solution to this problem. To really solve it in my own numerical library, I had to effectively implement arbitrary-precision floating point arithmetic and store a 320-digit (1078-bit) PI constant. Some implementations of libc effectively do this for you, but not all, so you can't safely assume it.
这篇关于三角自变量约简(模2π的约简)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!