有没有人知道(最好是快速)的方式来计算在4.12固定点的角度的正弦? (其中,其结果是一个圆的任32768ths或度)定点逆正弦
4.12定点装置的数目是16位并且被左移12,所以变为1.0(1 < < 12)或4096 0.5是(0.5 < < 12)== 2048等
有没有人知道(最好是快速)的方式来计算在4.12固定点的角度的正弦? (其中,其结果是一个圆的任32768ths或度)定点逆正弦
4.12定点装置的数目是16位并且被左移12,所以变为1.0(1 < < 12)或4096 0.5是(0.5 < < 12)== 2048等
如果您想要最高速度,预先计算是要走的路。既然你有可能的输入,那么天真的方法就是拥有一组16位的数值(对于总共128K的内存使用)。
但是,如果你不想使用所有的内存(以一点速度为代价),这可以稍微改进一点。
假设你输入的弧度(我假设他们是因为你的范围为4.12号码是0到15.999 ...,不足以代表一个圈中的所有度),你可以把事实的优点即:
sin (n) = sin (n % (2*PI)) for n >= 2*PI
sin (n) = -sin (n - PI) for PI <= n < 2*PI
sin (n) = sin (PI - n) for PI/2 <= n < PI
所以您的查找表只需要按住VA介于0和PI/2弧度之间,显着降低存储需求:您只能存储0到PI/2(〜1.571),而不是0到15.999的全部范围,减少90%。
然后你只需要值降低到低于2 * PI弧度与模数(第一个规则),并与其他两个规则修改它找到查找正确的索引。 Modulo将像整数一样快速地工作在固定点上。
所以,你会看这样的:
def sin(r):
if r >= PI_BY_2:
return sin (r % PI_BY_2)
if r >= PI:
return -sin (r - PI)
if r >= PI_DIV_2:
return sin (PI - r)
return sin_lookup[r]
def cos(r):
if r < PI_DIV_2:
return sin (r + PI_DIV_2_BY_3)
return sin (r - PI_DIV_2)
这cos
功能表明它是多么便宜,因为他们真的只是从正弦90度相移,以获得从同一个表余弦。
如果速度的极端重要性和记忆无关,只是使用全套指数因此无需进行计算。
另一个诀窍是,如果您愿意牺牲一些准确性,但使用较少内存的收益,则不会存储所有输入值的查找值。
鉴于正弦函数是平滑的一个(无间断),你可以存储每个第二值,并通过简单地平均那些在它的任一侧插对于那些在之间的值。
例如,如果我们有功能f(x) = x * x
,真正的和插值的一个表如下(假设我们只存储值甚至x
的x
奇数值进行插值,标有以下*
):
x real f(x) interpolated f(x)
-- --------- -----------------
0 0 0
1 1 2 *
2 4 4
3 9 10 *
4 16 16
5 25 26 *
6 36 36
7 49 50 *
8 64 64
9 91 82 *
10 100 100
,这不是一个完美的例如自从F之间的利差(x)的值可以是相当大的,但它适用于其中的值更紧密的功能更好。例如,sin(0),sin(1)和sin(2)(度,不是弧度)的实际值分别为0,0.017452406和0.034899496(这是斜率最大的地方)。 sin(0)和sin(2)的平均值为0.017449748,与实际值相比误差为0.0152%,其中一部分为6,500。
所以,最小误差,可以减少一半的内存要求的128K或六个半K.
用于表格查找的+1,但不是插值,您可能需要使用CORDIC。 – 2010-07-13 13:13:28
最快的方法是简单地预先计算它们并将其存储在查找表中。
当然,这一切都取决于您期望计算它的值的精度。更多细节会很好。
你在找什么语言约5%? C/C++? – 2009-11-15 03:21:27