sin
和cos
函数速度很慢,需要大量资源才能在嵌入式系统上运行。如何以更节省资源和更快速的方式计算sin
和cos
函数?
答案 0 :(得分:16)
答案 1 :(得分:10)
带插值的查找表无疑是最有效的解决方案。但是,如果你想使用更少的内存,CORDIC是计算trig函数值的一种非常有效的算法,通常在手持式计算器中实现。
作为一个侧面点,使用傅里叶级数表示这些函数没有任何意义,因为您只是创建了一个循环问题,即如何评估系列的sin / cos项。泰勒级数是一种众所周知的近似方法,但在许多情况下,误差大得令人无法接受。
您可能还想查看this question and its answers,关于Java的快速三角函数(因此代码可以轻松移植)。它提到了CORDIC和Chebyshev近似等。其中一个无疑将满足您的需求。
答案 2 :(得分:4)
取决于你需要它。如果您对角度精度不太满意(例如,如果最接近的度数可以),那么只需使用值的查找表。如果您没有FPU,请使用fixed-point。
计算 sin / cos函数的一种简单方法是使用泰勒级数(如三角函数here所示)。您使用的术语越少,值越准确,但计算越快。
傅里叶级数计算需要知道一些正弦/余弦值。但是,如果您在大多数情况下将事物存储在frequency domain中,则可以节省计算 - 取决于您正在做什么。
答案 3 :(得分:3)
Dr. Dobb的文章:Optimizing Math-Intensive Applications with Fixed-Point Arithmetic对CORDIC算法有很好的解释,并为本文讨论的库提供了完整的源代码。
答案 4 :(得分:2)
请注意,对于查找表,您通常可以通过限制域来优化事物,例如:将角度表示为无符号字符,在圆周围只有256步,但也是一个非常紧凑的表。可以对值进行类似的操作,例如使用定点。
答案 5 :(得分:2)
请参阅Stack Overflow问题How do Trigonometric functions work?那里接受的答案解释了如何进行范围缩减的一些细节,然后使用CORDIC,然后进行一些进一步的优化。
答案 6 :(得分:0)
但是,正如@unwind建议的那样,您可能希望尝试在一台不错的计算机上预先计算这些表,并将表加载到嵌入式设备中。
如果您的答案不一定非常精确,查找表会相当小,您将能够将其存储在设备的内存中。如果您需要更高的精度,则需要在设备中进行计算。这是记忆,时间和所需精度之间的权衡;答案取决于项目的具体性质。
答案 7 :(得分:0)
在某些情况下,人们可以使用IIR滤波器进行管理,调谐到所需频率的谐振。 看这里:http://www.ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf
答案 8 :(得分:0)
这可能有一些帮助/灵感: Magical square root in Quake III
答案 9 :(得分:0)
您可以查看这个用于8位AVR微控制器的任意定点库: https://community.atmel.com/projects/afp-arbitrary-fixed-point-lib
编辑:链接已更新
答案 10 :(得分:0)
我参加派对有点晚了,但无论如何我想分享一个现成的高效解决方案,使用查找表(包括表生成器):DFTrig。
DFTrig由两部分组成:
tablegen
(用Java编写,但并不重要)接收多个选项并生成C代码(带查找表的const结构)tablegen
生成的查找表的小C模块。当然,查找表仅包含最少的信息:仅一个象限的正弦值,即[0, 90]
度。这相当于计算任何角度的正弦/余弦。
行为非常可定制。您可以指定:
因此,根据您的需要,您可以:
我在我的嵌入式项目中使用它,效果很好。