Vla*_*lad 51
现代Intel/AMD处理器具有FSINCOS同时计算正弦和余弦函数的指令.如果您需要强大的优化,也许您应该使用它.
这是一个小例子:http://home.broadpark.no/~alein/fsincos.html
这是另一个例子(对于MSVC):http://www.codeguru.com/forum/showthread.php? t = 328669
这是另一个例子(使用gcc):http://www.allegro.cc/forums/thread/588470
希望其中一人有所帮助.(我自己没有使用这个说明,抱歉.)
由于它们在处理器级别上受支持,我希望它们比表查找快得多.
编辑:
维基百科建议FSINCOS在387处理器上添加,因此您很难找到不支持它的处理器.
编辑:
英特尔的文档说明FSINCOS比慢FDIV(即浮点除法)慢约5倍.
编辑:
请注意,并非所有现代编译器都将正弦和余弦的计算优化为调用FSINCOS.特别是,我的VS 2008并没有这样做.
编辑:
第一个示例链接已死,但Wayback机器上仍有一个版本.
Chi*_*Chi 38
现代x86处理器有一个fsincos指令,可以完全按照你的要求进行操作 - 同时计算sin和cos.一个好的优化编译器应检测为相同值计算sin和cos的代码,并使用fsincos命令执行此操作.
为此,需要花费一些编译器标志,但是:
$ gcc --version
i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5488)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ cat main.c
#include <math.h>
struct Sin_cos {double sin; double cos;};
struct Sin_cos fsincos(double val) {
struct Sin_cos r;
r.sin = sin(val);
r.cos = cos(val);
return r;
}
$ gcc -c -S -O3 -ffast-math -mfpmath=387 main.c -o main.s
$ cat main.s
.text
.align 4,0x90
.globl _fsincos
_fsincos:
pushl %ebp
movl %esp, %ebp
fldl 12(%ebp)
fsincos
movl 8(%ebp), %eax
fstpl 8(%eax)
fstpl (%eax)
leave
ret $4
.subsections_via_symbols
Run Code Online (Sandbox Code Playgroud)
Tada,它使用fsincos指令!
tan*_*ius 13
当您需要性能时,可以使用预先计算的sin/cos表(一个表将执行,存储为字典).嗯,这取决于你需要的准确性(也许表会很大),但它应该非常快.
Deb*_*ski 13
从技术上讲,你可以通过使用复数和欧拉公式来实现这一目标.因此,像(C++)
complex<double> res = exp(complex<double>(0, x));
// or equivalent
complex<double> res = polar<double>(1, x);
double sin_x = res.imag();
double cos_x = res.real();
Run Code Online (Sandbox Code Playgroud)
应该一步给你正弦和余弦.如何在内部完成这是一个使用的编译器和库的问题.它可能(并且可能)以这种方式花费更长的时间(仅仅因为欧拉公式主要用于exp使用sin和cos- 而不是相反的方式来计算复合体),但可能存在一些理论上的优化.
编辑
在标题<complex>为GNU C++ 4.2使用的明确的计算sin和cos内部polar,所以除非编译器做了一些魔术(见它不查找的优化有太好-ffast-math和-mfpmath开关写在驰的答案).
Mit*_*eat 12
您可以计算任何一个,然后使用标识:
cos(x)2 = 1 - sin(x)2
但正如@tanascius所说,预先计算好的表是可行的方法.
这个论坛页面上有非常有趣的东西,专注于找到快速的好近似值:http://www.devmaster.net/forums/showthread.php? t = 5784
免责声明:我自己没有使用任何这些东西.
更新于2018年2月22日:Wayback Machine是现在访问原始页面的唯一途径:https://web.archive.org/web/20130927121234/http: //devmaster.net/posts/9648/fast-and-accurate-正弦,余弦
如果您使用GNU C库,那么您可以:
#define _GNU_SOURCE
#include <math.h>
Run Code Online (Sandbox Code Playgroud)
你会得到的声明sincos(),sincosf()并sincosl()在你的目标体系以最快的方式可能-函数计算两个值在一起.
如caf所示,许多C数学库已经有了sincos().值得注意的例外是MSVC.
关于查找,Eric S. Raymond在" Unix编程艺术"(2004)(第12章)中明确指出这是一个坏主意(目前时刻):
"另一个例子是预先计算小型表格 - 例如,用于优化3D图形引擎中旋转的度数的sin(x)表将在现代机器上获得365×4字节.在处理器获得足够快于内存之前需要缓存这是一个明显的速度优化.现在每次重新计算可能会更快,而不是支付由表引起的额外缓存未命中的百分比.
"但是在未来,随着缓存变得越来越大,这种情况可能会再次出现.更一般地说,许多优化都是暂时的,随着成本比率的变化,很容易变成悲观情绪.唯一知道的方法就是衡量和看到." (来自Unix编程的艺术)
但是,从上面的讨论来看,并非所有人都同意.
我不相信查找表对于这个问题一定是个好主意.除非您的准确度要求非常低,否则表格必须非常大.现代CPU可以在从主存储器中获取值时进行大量计算.这不是可以通过论证(甚至不是我的),测试和测量并考虑数据来正确回答的那些问题之一.
但我会看看你在像AMD的ACML和英特尔的MKL这样的库中找到的SinCos的快速实现.