正弦半角公式的应用可以解决问题中提到的两个影响精度的问题:
sin(incr/2)=√((1-cos(incr))/2)¥
sinÁ(incr/2)=(1-cos(incr))/2
2·sinÁ(incr/2)=1-cos(incr)
1-2·sinÁ(incr/2)=cos(incr)
将其代入到原始公式中会得到这个中间表示:
sin(碱基+incr)=fma(-2·sinÁ(incr/2),sin(碱基),fma(sin(incr),cos(碱基),sin(碱基)))
cos(碱基+incr)=fma(-2·sinÁ(incr/2),cos(碱基),fma(-sin(incr),sin(碱基),cos(碱基)))
另一种选择是将单个FMA应用于改进的公式,尽管目前还不清楚两个乘法中的哪一个应该映射到FMA内部的非舍入乘法:
sin(碱基+incr)=sin(碱基)+fma(sin(incr),cos(碱基),-2·sin(incr/2)·sin(碱基))
cos(碱基+incr)=cos(碱基)-fma(sin(incr),sin(碱基),2·sin(incr/2)·cos(碱基))
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NAIVE (1)
#define ROBUST (2)
#define FAST (3)
#define ACCURATE (4)
#define MODE (ACCURATE)
// Fixes via: Greg Rose, KISS: A Bit Too Simple. http://eprint.iacr.org/2011/007
static unsigned int z=362436069,w=521288629,jsr=362436069,jcong=123456789;
#define znew (z=36969*(z&0xffff)+(z>>16))
#define wnew (w=18000*(w&0xffff)+(w>>16))
#define MWC ((znew<<16)+wnew)
#define SHR3 (jsr^=(jsr<<13),jsr^=(jsr>>17),jsr^=(jsr<<5)) /* 2^32-1 */
#define CONG (jcong=69069*jcong+13579) /* 2^32 */
#define KISS ((MWC^CONG)+SHR3)
int main (void)
{
double sumerrsqS, sumerrsqC, rmsS, rmsC, maxrmsS = 0, maxrmsC = 0;
double refS, refC, errS, errC;
float base, incr, s0, c0, s1, c1, tt;
int count, i;
const int N = 100; // # rotation steps per test case
count = 2000000; // # test cases (a pair of base and increment values)
#if MODE == NAIVE
printf ("testing: NAIVE (without FMA)\n");
#elif MODE == FAST
printf ("testing: FAST (without FMA)\n");
#elif MODE == ACCURATE
printf ("testing: ACCURATE (with FMA)\n");
#elif MODE == ROBUST
printf ("testing: ROBUST (with FMA)\n");
#else
#error unsupported MODE
#endif // MODE
do {
/* generate test case */
base = (float)(KISS * 1.21e-10); // starting angle, < 30 degrees
incr = (float)(KISS * 2.43e-10 / N); // increment, < 60/n degrees
/* set up rotation parameters */
s1 = sinf (incr);
#if MODE == NAIVE
c1 = cosf (incr);
#else
tt = sinf (incr * 0.5f);
c1 = 2.0f * tt * tt;
#endif // MODE
sumerrsqS = 0;
sumerrsqC = 0;
s0 = sinf (base); // initial sine
c0 = cosf (base); // initial cosine
/* run test case through N rotation steps */
i = 0;
do {
tt = s0; // old sine
#if MODE == NAIVE
/* least accurate, 6 FP ops */
s0 = c1 * tt + s1 * c0; // new sine
c0 = c1 * c0 - s1 * tt; // new cosine
#elif MODE == ROBUST
/* very accurate, 8 FP ops */
s0 = ( s1 * c0 - c1 * tt) + tt; // new sine
c0 = (-s1 * tt - c1 * c0) + c0; // new cosine
#elif MODE == FAST
/* accurate and fast, 4 FP ops */
s0 = fmaf (-c1, tt, fmaf ( s1, c0, tt)); // new sine
c0 = fmaf (-c1, c0, fmaf (-s1, tt, c0)); // new cosine
#elif MODE == ACCURATE
/* most accurate, 6 FP ops */
s0 = tt + fmaf (s1, c0, -c1 * tt); // new sine
c0 = c0 - fmaf (s1, tt, c1 * c0); // new cosine
#endif // MODE
i++;
refS = sin (fma ((double)i, (double)incr, (double)base));
refC = cos (fma ((double)i, (double)incr, (double)base));
errS = ((double)s0 - refS) / refS;
errC = ((double)c0 - refC) / refC;
sumerrsqS = fma (errS, errS, sumerrsqS);
sumerrsqC = fma (errC, errC, sumerrsqC);
} while (i < N);
rmsS = sqrt (sumerrsqS / N);
rmsC = sqrt (sumerrsqC / N);
if (rmsS > maxrmsS) maxrmsS = rmsS;
if (rmsC > maxrmsC) maxrmsC = rmsC;
} while (--count);
printf ("max rms error sin = % 16.9e\n", maxrmsS);
printf ("max rms error cos = % 16.9e\n", maxrmsC);
return EXIT_SUCCESS;
}
testing: NAIVE (without FMA)
max rms error sin = 4.837386842e-006
max rms error cos = 6.884047862e-006
testing: ROBUST (without FMA)
max rms error sin = 3.330292645e-006
max rms error cos = 4.297631502e-006
testing: FAST (with FMA)
max rms error sin = 3.532624939e-006
max rms error cos = 4.763623188e-006
testing: ACCURATE (with FMA)
max rms error sin = 3.330292645e-006
max rms error cos = 4.104813533e-006
/编辑:很抱歉缺少一个问题。我需要知道如何使用正弦和余弦来画一个正方形或矩形,旋转中心在正方形或矩形的左上角。用角度的sin和cos得到坐标(x1,y1),然后用角度的sin和cos函数加上90度得到坐标(x2,y2)。使用计数器变量从左到右,从上到下绘制线条,随角度变化。
问题内容: 我计算了两个文档的tf / idf值。以下是tf / idf值: 这些文件就像: 如何使用这些值来计算余弦相似度? 我知道我应该计算点积,然后找到距离并除以点积。如何使用我的值来计算? 还有一个问题: 两个文档的字数相同是否重要? 问题答案: a * b是点积 一些细节: 是。在某种程度上,a和b必须具有相同的长度。但是a和b通常具有稀疏表示,您只需要存储非零条目,就可以更快地计算范数
我试图生成一组点,当绘制成一个图表示1个周期的正弦波。要求是: 1个周期的正弦波 下限=29491 上限=36043 点数=100 振幅=3276 零偏移量=32767 代码: 我正在生成并存储一个文件中的点。当这些点被绘制出来时,我得到了下面的图。 但我只需要一个循环。我怎么能这么做?
用C/C++编写了一个三维正弦波发生器 代码:
我如何建立一个方程来产生扫频正弦波。我是信号处理新手,在网上找不到太多关于生成扫描正弦波的话题。请告诉我一些我可以用来生成方程式并在代码中使用的源代码。非常感谢。
我在许多正弦/余弦的应用中都看到了一种所谓的扩展模精度算法。但这是为了什么?例如,在cephes实验中,在缩小到[0,pi/4]范围后,他们正在进行这种模块化精度算法来提高精度。 守则如下: 其中DP1、DP2和DP3是一些硬编码系数。如何从数学上求出这些系数?我已经理解了“模块扩展算术”对于big num的目的,但是这里它的确切目的是什么呢?