从 sin(a) 得到 cos(a) 的最佳方法
将 s
作为某个(未知)角度“a”的正弦,获得“a 的余弦”的最快方法是什么?
我知道两种明显的方法:
c = cos(asin(s));
和
c = sqrt(1 - s*s);
但我不知道函数 cos()、asin() 和 sqrt() 的实现在速度方面如何相互比较。一个比另一个快多快?它们在现代处理器中的实现(例如 x86-64 和带有 VFP 的 ARM)之间是否存在显着差异?最后,更好的解决方案是什么?
编辑:由于现在已经有 3 个不相关的答案,让我澄清一下:我最初没有角度,我拥有的只是正弦。所以不需要告诉我将角度旋转 90 度,这样我就可以从其他函数获得相同的值......
Having s
as sine of some (unknown) angle "a", what is the fastest way to get the "cosine of a"?
I know two obivious ways:
c = cos(asin(s));
and
c = sqrt(1 - s*s);
But I don't know how the implementation of the functions cos(), asin() and sqrt() compares to one another in regarding speed. How faster is one over another? Are there significant difference between their implementations in modern processors, say, between x86-64 and ARM with VFP? In the end, what is the better solution?
Edit: Since there are already 3 unrelated answers now, let me clarify: I don't initally have the angle, all I have is the sine. So there is no need to tell me to rotate the angle 90 degrees so I'll have the same value from the other function...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一种方法:
您需要找出不同的象限(即分别 cos() 的符号)。如果您拥有的只是 sin() 值(不同角度可以具有相同的 sin() 但 cos() 符号不同),则这是不可能的。
正如其他人指出的那样,查找表实际上可能是最快的。取决于你需要什么精度。这几乎肯定会比你的 cos(asin()) 版本更快,并且 平方根也可以在实践中进行优化。
在我的 Core i3 笔记本电脑上,使用 Visual Studio 2010,此方法的性能比基于三角函数的版本(具有快速浮点选项)快约 6 倍(每次调用约 20 纳秒)。让我们看看生成的代码:
快速浮点选项,使用平方根:
使用三角函数:
当切换到精确浮点模式时,生成的三角代码使用不同的函数(大概是 SSE 优化版本牺牲了精度):
Here's one way:
You need to figure out the different quadrants (i.e. the sign of the cos() seperately). This is not possible if all you have is the sin() value (different angles can have the same sin() but cos() differs by sign).
As other people noted a lookup table may in practice be the fastest. Depends on what precision you require. This is almost certainly going to be faster than your cos(asin()) version and the square root can also be optimized in practice.
Using Visual studio 2010 the performance of this method is about 6 times faster than the trig based version (with fast floating point option) on my Core i3 laptop (about 20ns per call). Let's look at the generated code:
Fast floating point option, using square root:
Using trig functions:
When switching to precise floating point mode the generated trig code uses different functions (presumably the SSE optimized versions sacrifices accuracy):
最好的方法是使用 eps * sqrt(1 - s * s) ,其中 eps 是加或减 1。这是最好的方法
因为计算 的余弦如果你处于“接近一”的情况,反正弦可能会失去精度(练习:1/为什么?提示:记住 sin 在 pi/2 处最大,其导数消失 2/ 尝试一下。) 编辑:我说得太快了,因为当1 - s * s
保持接近于 1,因此计算平方根的误差很小。s
接近1时,sqrt(1 - s * s)
也有同样的问题。asin
的作用(可能相当昂贵),cos
可能比 sqrt 慢一个数量级,因此一个平方根可能比这两个超越函数调用更快。有疑问,个人资料(但我准备赌一些钱)。忘记查找表,直到您证明
sqrt(1 - s * s)
对您来说不够快(即使如此,您也可以找到方法来权衡一些sqrt
代码>速度的准确性)。The best way is to use
eps * sqrt(1 - s * s)
, whereeps
is plus or minus one. It is the best waysinceComputing the cosine of the arc sine may lose you precision if you are in the 'near one' case (exercise: 1/ why ? hint: remember that sin is maximal at pi/2 and its derivative vanishes 2/ Try it.) EDIT: I spoke too fast, since1 - s * s
stays close to one and therefore the error in computing the square root is minimal.sqrt(1 - s * s)
has the same problems whens
is close to one.asin
does (probably quite costly),cos
is likely to be one order of magnitude slower thansqrt
, and thus one square root is likely to be quickier than those two transcendental function calls. In doubt, profile (but I'm ready to bet some money).Forget about look up tables until you have proven that
sqrt(1 - s * s)
is not fast enough for you (and even there, you can find ways to trade off somesqrt
accuracy for speed).用极坐标可视化单位圆。 r=1,theta =(角度)。则单位圆上 X,Y(笛卡尔)坐标中的任意点为 ( cos( theta ), sin ( theta ))。
visualize the unit circle with polar coordinates. r=1, theta = (the angle ). then any point on the unit circle in X,Y ( cartesian ) coordinates is ( cos( theta ), sin ( theta )).
Sin 和 Cos 只是同一条曲线偏移二分之一弧度(或 90 度),因此:
pi 为 3.14159...
Sin and Cos are simply the same curve offset by one-half radian (or 90 degrees), so:
pi being 3.14159...
如果您的 sin/cos 函数采用弧度:
如果您的 sin/cos 函数采用度数:
If your sin/cos functions take radians:
If your sin/cos functions take degrees: