如何将以下伪代码重写为C++?
real array sine_table[-1000..1000]
for x from -1000 to 1000
sine_table[x] := sine(pi * x / 1000)
我需要创建一个正弦表查找表。如何将以下伪代码重写为C++?
real array sine_table[-1000..1000]
for x from -1000 to 1000
sine_table[x] := sine(pi * x / 1000)
我需要创建一个正弦表查找表。通过仅存储第一象限(即x在[0,pi/2])的值,您可以将表格的大小减小为原来的25%。
要做到这一点,您的查找程序只需要使用简单的三角恒等式将所有x的值映射到第一象限:
要从第三象限映射到第一象限,请应用两个恒等式,即sin(x) = - sin (pi + x)
这种策略是否有所帮助取决于内存使用对您的案例有多重要。但是,存储四倍于您需要的值只是为了避免在查找期间进行比较和减法似乎是浪费的。
我赞同Jeremy的建议,即测量构建表格是否比仅使用std :: sin()更好。即使使用原始大表格,您每次查找表格时也必须花费周期来将参数转换为最接近pi / 1000的增量,并且在此过程中会失去一些精度。
如果您真的想要以速度为代价交换精度,则可以尝试仅使用Taylor级数展开的前几个项来逼近sin()函数。
当然,为了效率,您应该预先计算阶乘并利用较低次幂的x来计算更高次幂,例如在计算x^5时使用x^3。
最后一个要点是,上面截断的Taylor级数对于接近零的值更精确,因此在计算近似正弦之前将其映射到第一或第四象限仍然是有价值的。
补充说明:
基于两个观察到的潜在改进:
1.如果您可以在第一个八分之一[0,pi/4]中计算出正弦和余弦,则可以计算任何三角函数
2.以零为中心的Taylor级数展开在接近零时更精确
sin(-x) = -sin(x)
。 - Ben Voigt还有一点需要注意:调用三角函数的代价很高。如果你想要为正弦函数准备具有恒定步长的查找表,你可以节省计算时间,但会损失一些潜在的精度。
假设你的最小步长为“a”。也就是说,你需要 sin(a),sin(2a),sin(3a) 等等。
那么你可以使用以下技巧:首先计算 sin(a) 和 cos(a)。然后对于每个连续的步骤,使用以下三角函数等式:
这种方法的缺点是在此过程中会积累舍入误差。
long double sine_table[2001];
for (int index = 0; index < 2001; index++)
{
sine_table[index] = std::sin(PI * (index - 1000) / 1000.0);
}
#include <cmath>
。sine_table[-1000..999]
。
double table[1000] = {0};
for (int i = 1; i <= 1000; i++)
{
sine_table[i-1] = std::sin(PI * i/ 1000.0);
}
double getSineValue(int multipleOfPi){
如果(multipleOfPi == 0) 返回0.0;
int 符号 = 1;
如果(multipleOfPi < 0){
符号 = -1;
}
返回符号sine_table[符号multipleOfPi - 1];
}
您可以通过技巧sin(pi/2 +/- angle) = +/- cos(angle)将数组长度缩小到500。 所以存储0到pi/4的sin和cos。 我不记得从头脑中提取的内容,但它加速了我的程序。
<cmath>
中的std::sin()
函数。以下是从某本书或其他来源获得的另一种近似方法:
streamin ramp;
streamout sine;
float x,rect,k,i,j;
x = ramp -0.5;
rect = x * (1 - x < 0 & 2);
k = (rect + 0.42493299) *(rect -0.5) * (rect - 0.92493302) ;
i = 0.436501 + (rect * (rect + 1.05802));
j = 1.21551 + (rect * (rect - 2.0580201));
sine = i*j*k*60.252201*x;
streamin ramp;
streamin x; // 1.5 = Saw 3.142 = Sin 4.5 = SawSin
streamout sine;
float saw,saw2;
saw = (ramp * 2 - 1) * x;
saw2 = saw * saw;
sine = -0.166667 + saw2 * (0.00833333 + saw2 * (-0.000198409 + saw2 * (2.7526e-006+saw2 * -2.39e-008)));
sine = saw * (1+ saw2 * sine);
sin
函数吗?还是应对需要负数索引的情况?或者是声明一个数组?或者是在 C++ 中编写for
循环?亦或是找到代表实数类型的名称?还是全部都需要帮助? - Steve Jessopx — (x^3)/(3!) + (x^5)/(5!) — (x^7)/(7!) + ...
更快。 - Mike DeSimonesin
方法的情况下计算正弦函数的值”。在这种情况下,泰勒是最著名的软件实现算法,但是计算机ALU、计算器和其他数字系统通常通过硬件模拟正弦函数(以及许多其他函数),实现CORDIC(示例)。它比完整的查找表具有更轻的占用空间。 - mins