CORDIC算法与泰勒级数计算三角函数sin,cos的速度与精度对比

在学习CORDIC(Coordinate Rotation Digital Computer)算法的时候,最主要的疑问是:浮点数怎么做移位运算?如果CORDIC算法中不使用移位运算,而是直接使用浮点数乘法(除以浮点常数的除法会被C++编译器优化为乘法),那么CORDIC算法的浮点乘法次数大大超过同精度的泰勒级数,完全失去了加快计算速度的意义。本文的代码使用整型变量实现CORDIC算法中的移位运算,并与浮点数实现的泰勒级数算法进行速度与精度的对比。在电脑和Arduino nano上进行了测试:两个不同平台上,泰勒级数的速度均大大超过了CORDIC算法。在电脑CPU上,泰勒级数的速度与标准库接近。在Arduino nano上,泰勒级数的速度只有标准库的一半。


因为电脑CPU都有专门的浮点运算单元(FPU),所以浮点乘法相较于移位运算,耗时并没有长太多。Arduino nano是没有FPU的,按理说浮点乘法速度很慢(参见 https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html),CORDIC算法应该比泰勒级数快,但测试结果恰好相反,可能是因为我写得cordic函数用了   

int n = (int)(Q * d2_pi);      
Q -= n * pi_2;
return cosSign * x * scale;
return sinSign * y * scale;

这些浮点运算。

注意,在电脑上的代码中,数组angles的类型是浮点数,在Arduino nano上,angles(x1e8)的类型是32bit的整数,就是对应的浮点数乘上10^8再取整。这样做比使用浮点型的angles要快得多。

#include <stdio.h>
#include <cstdint>
#include <math.h>
#include <time.h>
#include <bitset>
#include <immintrin.h>

//#define SINGLE_PRECISION
#define FMADD

// K=1/(sqrt(1+1)*sqrt(1+1/4)*sqrt(1+1/16)*sqrt(1+1/64)...) 是一个无穷乘积
// K=0.6072529350088812561694467525049282631124...
// 在单精度情形,先将K * 10^9化成整数(要确保不超过2^32 =4294967296),
// 再进行加减法和移位运算,最后乘上1e-9化为浮点数。双精度情形类似。

#ifdef SINGLE_PRECISION
typedef float real;
typedef int32_t integer;
constexpr int32_t K = 607252935;
//             2^32 =4294967296
constexpr float scale = 1e-9;
constexpr uint8_t numIter = 32;  //设得更大就会出错

constexpr float pi_2 = 1.570796326794897;    // pi/2
constexpr float d2_pi = 0.6366197723675814;  // 2/pi
constexpr float pi_128 = 0.02454369260617026;  // pi/128
constexpr float d128_pi = 40.74366543152521;   // 128/pi
#else
typedef double real;
typedef int64_t integer;
constexpr int64_t K = 607252935008881256;
//             2^64 =18446744073709551616
constexpr double scale = 1e-18;
constexpr uint8_t numIter = 40;

constexpr double pi_2 = 1.570796326794897;    // pi/2
constexpr double d2_pi = 0.6366197723675814;  // 2/pi
constexpr double pi_128 = 0.02454369260617026;  // pi/128
constexpr double d128_pi = 40.74366543152521;   // 128/pi
#endif

// 如果constexpr int64_t K =  6072529350088812561;
//                     2^64 =18446744073709551616
//                     2^63 = 9223372036854775808
// constexpr double scale = 1e-19;
// 
// 则Q=1.5时,迭代中会出现x,y超过2^63的情况,导致溢出
// 把int64_t改为uint64_t也不行,Q=1.5时,会出现小数减大数的情况,导致错误。

struct {
	const char cosine = 0;
	const char sine = 1;
}triangle;

// atan(1), atan(1/2), atan(1/4), atan(1/8), atan(1/16), atan(1/32), atan(1/64), ...
constexpr real angles[41] = {
0.785398163397448, 0.463647609000806, 0.244978663126864, 0.124354994546761,
0.062418809995957, 0.031239833430268, 0.015623728620477, 0.007812341060101,
0.003906230131967, 0.001953122516479, 0.000976562189559, 0.000488281211195,
0.000244140620149, 0.000122070311894, 0.000061035156174, 0.000030517578116,
0.000015258789061, 0.000007629394531, 0.000003814697266, 0.000001907348633,
0.000000953674316, 0.000000476837158, 0.000000238418579, 0.000000119209290,
0.000000059604645, 0.000000029802322, 0.000000014901161, 0.000000007450581,
0.000000003725290, 0.000000001862645, 0.000000000931323, 0.000000000465661,
0.000000000232831, 0.000000000116415, 0.000000000058208, 0.000000000029104,
0.000000000014552, 0.000000000007276, 0.000000000003638, 0.000000000001819,
0.000000000000909 };

// cos(0),cos(pi/128),cos(2*pi/128),...,cos(63*pi/128),cos(pi/2)
constexpr real cosTable[65] = {
1.0,
0.9996988186962042, 0.9987954562051724, 0.9972904566786902, 0.9951847266721969,
0.9924795345987100, 0.9891765099647810, 0.9852776423889412, 0.9807852804032304,
0.9757021300385286, 0.9700312531945440, 0.9637760657954398, 0.9569403357322088,
0.9495281805930367, 0.9415440651830208, 0.9329927988347390, 0.9238795325112867,
0.9142097557035307, 0.9039892931234433, 0.8932243011955153, 0.8819212643483550,
0.8700869911087115, 0.8577286100002721, 0.8448535652497071, 0.8314696123025452,
0.8175848131515837, 0.8032075314806449, 0.7883464276266063, 0.7730104533627370,
0.7572088465064846, 0.7409511253549592, 0.7242470829514670, 0.7071067811865476,
0.6895405447370669, 0.6715589548470184, 0.6531728429537769, 0.6343932841636455,
0.6152315905806268, 0.5956993044924335, 0.5758081914178453, 0.5555702330196023,
0.5349976198870973, 0.5141027441932217, 0.4928981922297841, 0.4713967368259978,
0.4496113296546066, 0.4275550934302822, 0.4052413140049899, 0.3826834323650898,
0.3598950365349883, 0.3368898533922201, 0.3136817403988916, 0.2902846772544623,
0.2667127574748984, 0.2429801799032640, 0.2191012401568698, 0.1950903220161283,
0.1709618887603014, 0.1467304744553617, 0.1224106751992163, 0.0980171403295608,
0.0735645635996675, 0.0490676743274181, 0.0245412285229123, 0.0,
};

real cordic(real Q, char cos_or_sin) {     // Q的单位是弧度
	short sinSign = 1, cosSign = 1;
	if (Q < 0)
	{
		Q = -Q;
		sinSign = -1;
	}
	int n = (int)(Q * d2_pi);
	Q -= n * pi_2;  // 减去pi/2的整数倍
	switch (n % 4) {
	case 1:        // 去掉负号的原始的Q是第二象限角
		Q = pi_2 - Q;
		cosSign = -1;
		break;
	case 2:		   // 第三象限角
		cosSign = -1;
		sinSign *= -1;
		break;
	case 3:		   // 第四象限角
		Q = pi_2 - Q;
		sinSign *= -1;
		break;
	}

	integer x = K, y = 0, temp;
	real  q = 0.0;
	for (uint8_t n = 0; n < numIter; n++) {
		if (q < Q) {
			temp = x - (y >> n);
			y = (x >> n) + y;
			x = temp;
			q += angles[n];
		}
		else {
			temp = x + (y >> n);
			y = y - (x >> n);
			x = temp;
			q -= angles[n];
		}
	}
	if (cos_or_sin == triangle.cosine)
	{
		return cosSign * x * scale;  // cosQ
	}
	else
	{
		return sinSign * y * scale;  // sinQ
	}
}

#define cordic_sin(Q) cordic((Q), triangle.sine)
#define cordic_cos(Q) cordic((Q), triangle.cosine)
//real cordic_sin(real Q) {
//	return cordic(Q, triangle.sine);
//}
//
//real cordic_cos(real Q) {
//	return cordic(Q, triangle.cosine);
//}

real taylor_cos_sin(real Q, char cos_or_sin) {
	int sinSign = 1, cosSign = 1;
	if (Q < 0)
	{
		Q = -Q;
	}

	int n = (int)(Q * d2_pi);
	Q -= n * pi_2;  // 减去pi/2的整数倍
	switch (n % 4) {
	case 1:        // 去掉负号的原始的Q是第二象限角
		Q = pi_2 - Q;
		cosSign = -1;
		break;
	case 2:		   // 第三象限角
		cosSign = -1;
		sinSign *= -1;
		break;
	case 3:		   // 第四象限角
		Q = pi_2 - Q;
		sinSign *= -1;
		break;
	}

	// 0<= Q <=pi/2
	n = (int)(Q * d128_pi);  // n=0,1,2,...,63
	Q -= n * pi_128;
	real Q2 = Q * Q;

#ifdef FMADD
	__m128d Q2_128 = _mm_set_sd(Q2);
	// 再提高泰勒级数的阶数也无法提高精度了。
	__m128d cosSmallQ128 = _mm_set_sd(-1.3888888888888889e-03);
	cosSmallQ128 = _mm_fmadd_sd(cosSmallQ128, Q2_128, _mm_set_sd(4.1666666666666667e-02));
	cosSmallQ128 = _mm_fmadd_sd(cosSmallQ128, Q2_128, _mm_set_sd(-5.0000000000000000e-01));
	cosSmallQ128 = _mm_fmadd_sd(cosSmallQ128, Q2_128, _mm_set_sd(1.0));
	real cosSmallQ = _mm_cvtsd_f64(cosSmallQ128);
	//---------------------------------------------------
	__m128d sinSmallQ128 = _mm_set_sd(8.3333333333333333e-03);
	sinSmallQ128 = _mm_fmadd_sd(sinSmallQ128, Q2_128, _mm_set_sd(-1.6666666666666667e-01));
	sinSmallQ128 = _mm_fmadd_sd(sinSmallQ128, Q2_128, _mm_set_sd(1.0));
	sinSmallQ128 = _mm_mul_sd(sinSmallQ128, _mm_set_sd(Q));
	real sinSmallQ = _mm_cvtsd_f64(sinSmallQ128);
#else
	real cosSmallQ = -1.3888888888888889e-03;
	cosSmallQ = cosSmallQ * Q2 + 4.1666666666666667e-02;
	cosSmallQ = cosSmallQ * Q2 - 5.0000000000000000e-01;
	cosSmallQ = cosSmallQ * Q2 + 1.0;
	//---------------------------------------------------
	real sinSmallQ = 8.3333333333333333e-03;
	sinSmallQ = sinSmallQ * Q2 - 1.6666666666666667e-01;
	sinSmallQ = sinSmallQ * Q2 + 1.0;
	sinSmallQ = sinSmallQ * Q;
#endif

	if (cos_or_sin == triangle.cosine)
	{   // cos(n*pi/128+SmallQ)=cos(n*pi/128)cos(SmallQ)-sin(n*pi/128)sin(SmallQ)
		return cosSign * (cosTable[n] * cosSmallQ - cosTable[64 - n] * sinSmallQ);
	}
	else
	{   // sin(n*pi/128+SmallQ)=sin(n*pi/128)cos(SmallQ)+cos(n*pi/128)sin(SmallQ)
		return sinSign * (cosTable[n] * sinSmallQ + cosTable[64 - n] * cosSmallQ);
	}
}

#define taylor_sin(Q) taylor_cos_sin((Q), triangle.sine)
#define taylor_cos(Q) taylor_cos_sin((Q), triangle.cosine)

//real taylor_sin(real Q) {
//	return taylor_cos_sin(Q, triangle.sine);
//}
//
//real taylor_cos(real Q) {
//	return taylor_cos_sin(Q, triangle.cosine);
//}


int main() {
	real Q;

	printf("double,精度测试\n");
	for (uint8_t n = 1; n < 16; n++) {
		Q = 0.1 * n;

		printf("    Q = %f\n", Q);
		printf("CORDIC: %16.15f, %16.15f\n", cordic_sin(Q), cordic_cos(Q));
		printf("taylor: %16.15f, %16.15f\n", taylor_sin(Q), taylor_cos(Q));
		printf("math.h: %16.15f, %16.15f\n", sin(Q), cos(Q));
		printf("---------------------------------\n");
	}
	/
	printf("速度测试,VS编译器优化设为 最大优化(优选速度)(/O2) \n");
	clock_t start = clock();
	double sum = 0.0;
	const double N = 1e8;
	const double c = 64.32 / N;
	for (double i = 1.0; i < N; i += 1.0) {
		Q = c * i;
		sum = sum + cordic_sin(Q) + cordic_cos(Q);
	}
	printf("sum=%f,  CORDIC_Time: %fs\n", sum, (double)(clock() - start) / CLOCKS_PER_SEC);
	
	start = clock();
	sum = 0.0;
	for (double i = 1.0; i < N; i += 1.0) {
		Q = c * i;
		sum = sum + taylor_sin(Q) + taylor_cos(Q);
	}
	printf("sum=%f,  Taylor_Time: %fs\n", sum, (double)(clock() - start) / CLOCKS_PER_SEC);
	
	start = clock();
	sum = 0.0;
	for (double i = 1.0; i < N; i += 1.0) {
		Q = c * i;
		sum = sum + sin(Q) + cos(Q);
	}
	printf("sum=%f,  math.h_Time: %fs\n", sum, (double)(clock() - start) / CLOCKS_PER_SEC);

	return 0;
}

CPU:Intel Core i7 12700H, 开发环境VS2022,使用双精度计算时,输出结果如下:

double,精度测试
    Q = 0.100000
CORDIC: 0.099833416646617, 0.995004165278047
taylor: 0.099833416646828, 0.995004165278026
math.h: 0.099833416646828, 0.995004165278026
---------------------------------
    Q = 0.200000
CORDIC: 0.198669330794285, 0.980066577841399
taylor: 0.198669330795061, 0.980066577841242
math.h: 0.198669330795061, 0.980066577841242
---------------------------------
    Q = 0.300000
CORDIC: 0.295520206662469, 0.955336489125257
taylor: 0.295520206661340, 0.955336489125606
math.h: 0.295520206661340, 0.955336489125606
---------------------------------
    Q = 0.400000
CORDIC: 0.389418342309467, 0.921060994002540
taylor: 0.389418342308651, 0.921060994002885
math.h: 0.389418342308651, 0.921060994002885
---------------------------------
    Q = 0.500000
CORDIC: 0.479425538604363, 0.877582561890286
taylor: 0.479425538604203, 0.877582561890373
math.h: 0.479425538604203, 0.877582561890373
---------------------------------
    Q = 0.600000
CORDIC: 0.564642473394510, 0.825335614910038
taylor: 0.564642473395035, 0.825335614909678
math.h: 0.564642473395035, 0.825335614909678
---------------------------------
    Q = 0.700000
CORDIC: 0.644217687238764, 0.764842187283585
taylor: 0.644217687237691, 0.764842187284488
math.h: 0.644217687237691, 0.764842187284488
---------------------------------
    Q = 0.800000
CORDIC: 0.717356090900460, 0.696706709346200
taylor: 0.717356090899523, 0.696706709347165
math.h: 0.717356090899523, 0.696706709347165
---------------------------------
    Q = 0.900000
CORDIC: 0.783326909627326, 0.621609968270863
taylor: 0.783326909627484, 0.621609968270664
math.h: 0.783326909627483, 0.621609968270664
---------------------------------
    Q = 1.000000
CORDIC: 0.841470984807630, 0.540302305868554
taylor: 0.841470984807897, 0.540302305868140
math.h: 0.841470984807897, 0.540302305868140
---------------------------------
    Q = 1.100000
CORDIC: 0.891207360060892, 0.453596121426645
taylor: 0.891207360061436, 0.453596121425577
math.h: 0.891207360061435, 0.453596121425577
---------------------------------
    Q = 1.200000
CORDIC: 0.932039085967490, 0.362357754475995
taylor: 0.932039085967227, 0.362357754476673
math.h: 0.932039085967226, 0.362357754476673
---------------------------------
    Q = 1.300000
CORDIC: 0.963558185417581, 0.267498828623190
taylor: 0.963558185417193, 0.267498828624587
math.h: 0.963558185417193, 0.267498828624587
---------------------------------
    Q = 1.400000
CORDIC: 0.985449729988356, 0.169967142900846
taylor: 0.985449729988460, 0.169967142900241
math.h: 0.985449729988460, 0.169967142900241
---------------------------------
    Q = 1.500000
CORDIC: 0.997494986603962, 0.070737201669002
taylor: 0.997494986604054, 0.070737201667703
math.h: 0.997494986604054, 0.070737201667703
---------------------------------
速度测试,VS编译器优化设为 最大优化(优选速度)(/O2)
sum=2975793.653839,  CORDIC_Time: 22.525000s
sum=2975793.653839,  Taylor_Time: 0.965000s
sum=2975793.653839,  math.h_Time: 0.933000s

Arduino nano(Atmel 328P)上的代码和结果如下:

//            K=0.6072529350088812561694467525049282631124
constexpr int32_t K = 607252935;
//             2^32 =4294967296
constexpr float scale = 1e-9f;
constexpr uint8_t numIter = 25;

constexpr float pi_2 = 1.5707964f;      // pi/2
constexpr float d2_pi = 0.63661975f;    // 2/pi
constexpr float pi_128 = 0.024543693f;  // pi/128
constexpr float d128_pi = 40.743664f;   // 128/pi
constexpr int32_t pi_2x1e8 = 157079633;    // pi/2 * 1e8

struct {
	const char cosine = 0;
	const char sine = 1;
}triangle;

// [atan(1), atan(1/2), atan(1/4), atan(1/8), atan(1/16), atan(1/32), atan(1/64), ...]*1e8
constexpr int32_t anglesx1e8[27] = {
78539816, 46364761, 24497866, 12435499,
6241881, 3123983, 1562373, 781234,
390623, 195312, 97656, 48828,
24414, 12207, 6104, 3052,
1526, 763, 381, 191,
95, 48, 24, 12,
6, 3, 1 };

// cos(0),cos(pi/128),cos(2*pi/128),...,cos(63*pi/128),cos(pi/2)
constexpr float cosTable[65] = {
  1.0f,
  0.99969882f, 0.99879546f, 0.99729046f, 0.99518473f,
  0.99247953f, 0.98917651f, 0.98527764f, 0.98078528f,
  0.97570213f, 0.97003125f, 0.96377607f, 0.95694034f,
  0.94952818f, 0.94154407f, 0.93299280f, 0.92387953f,
  0.91420976f, 0.90398929f, 0.89322430f, 0.88192126f,
  0.87008699f, 0.85772861f, 0.84485357f, 0.83146961f,
  0.81758481f, 0.80320753f, 0.78834643f, 0.77301045f,
  0.75720885f, 0.74095113f, 0.72424708f, 0.70710678f,
  0.68954054f, 0.67155895f, 0.65317284f, 0.63439328f,
  0.61523159f, 0.59569930f, 0.57580819f, 0.55557023f,
  0.53499762f, 0.51410274f, 0.49289819f, 0.47139674f,
  0.44961133f, 0.42755509f, 0.40524131f, 0.38268343f,
  0.35989504f, 0.33688985f, 0.31368174f, 0.29028468f,
  0.26671276f, 0.24298018f, 0.21910124f, 0.19509032f,
  0.17096189f, 0.14673047f, 0.12241068f, 0.09801714f,
  0.07356456f, 0.04906767f, 0.02454123f, 0.0f
};

float cordic(float Q, char cos_or_sin) {     // Q的单位是弧度
	int sinSign = 1, cosSign = 1;
	if (Q < 0)
	{
		Q = -Q;
		sinSign = -1;
	}
	const int32_t n = (int32_t)(Q * d2_pi);
	Q -= n * pi_2;  // 减去pi/2的整数倍
	int32_t intQ = Q * 1e8f;
	switch (n % 4) {
	case 1:        // 去掉负号的原始的Q是第二象限角
		intQ = pi_2x1e8 - intQ;
		cosSign = -1;
		break;
	case 2:		   // 第三象限角
		cosSign = -1;
		sinSign *= -1;
		break;
	case 3:		   // 第四象限角
		intQ = pi_2x1e8 - intQ;
		sinSign *= -1;
		break;
	}

	int32_t x = K, y = 0, temp;
	int32_t q = 0;
	for (uint8_t n = 0; n < numIter; n++) {
		if (q < intQ) {
			temp = x - (y >> n);
			y = (x >> n) + y;
			x = temp;
			q += anglesx1e8[n];
		}
		else {
			temp = x + (y >> n);
			y = y - (x >> n);
			x = temp;
			q -= anglesx1e8[n];
		}
	}
	if (cos_or_sin == triangle.cosine)
	{
		return cosSign * x * scale;  // cosQ
	}
	else
	{
		return sinSign * y * scale;  // sinQ
	}
}

#define cordic_sin(Q) cordic((Q), triangle.sine)
#define cordic_cos(Q) cordic((Q), triangle.cosine)

float taylor_cos_sin(float Q, char cos_or_sin) {
	int sinSign = 1, cosSign = 1;
	if (Q < 0)
	{
		Q = -Q;
	}

	int n = (int)(Q * d2_pi);
	Q -= n * pi_2;  // 减去pi/2的整数倍
	switch (n % 4) {
	case 1:        // 去掉负号的原始的Q是第二象限角
		Q = pi_2 - Q;
		cosSign = -1;
		break;
	case 2:		   // 第三象限角
		cosSign = -1;
		sinSign *= -1;
		break;
	case 3:		   // 第四象限角
		Q = pi_2 - Q;
		sinSign *= -1;
		break;
	}

	// 0<= Q <=pi/2
	n = (int)(Q * d128_pi);  // n=0,1,2,...,63
	Q -= n * pi_128;
	float Q2 = Q * Q;

	float cosSmallQ = -1.3888889e-03f;
	cosSmallQ = cosSmallQ * Q2 + 4.1666668e-02f;
	cosSmallQ = cosSmallQ * Q2 - 0.5f;
	cosSmallQ = cosSmallQ * Q2 + 1.0f;
	//---------------------------------------------------
	float sinSmallQ = 8.3333333e-03f;
	sinSmallQ = sinSmallQ * Q2 - 1.6666667e-01f;
	sinSmallQ = sinSmallQ * Q2 + 1.0f;
	sinSmallQ = sinSmallQ * Q;

	if (cos_or_sin == triangle.cosine)
	{   // cos(n*pi/128+SmallQ)=cos(n*pi/128)cos(SmallQ)-sin(n*pi/128)sin(SmallQ)
		return cosSign * (cosTable[n] * cosSmallQ - cosTable[64 - n] * sinSmallQ);
	}
	else
	{   // sin(n*pi/128+SmallQ)=sin(n*pi/128)cos(SmallQ)+cos(n*pi/128)sin(SmallQ)
		return sinSign * (cosTable[n] * sinSmallQ + cosTable[64 - n] * cosSmallQ);
	}
}

#define taylor_sin(Q) taylor_cos_sin((Q), triangle.sine)
#define taylor_cos(Q) taylor_cos_sin((Q), triangle.cosine)

void setup() {
  Serial.begin(9600);
}

void loop() {
  float Q;
  Serial.println("Accuracy Test");
  for (uint8_t n = 1; n < 16; n++) {
    Q = 0.1 * n;
    Serial.println("Q = " + String(Q, 4));
    Serial.println("CORDIC: sin(Q) = " + String(cordic_sin(Q), 7) + ", cos(Q) = " + String(cordic_cos(Q), 7));
    Serial.println("taylor: sin(Q) = " + String(taylor_sin(Q), 7) + ", cos(Q) = " + String(taylor_cos(Q), 7));
    Serial.println("math.h: sin(Q) = " + String(sin(Q), 7) + ", cos(Q) = " + String(cos(Q), 7));
    Serial.println("---------------------------------");
  }
  /
  Serial.println("Speed Test");
  float start = millis();
  float sum = 0.0;
  const int N = 3000;
  const float c = 6.432 / N;
  for (int i = 1; i < N; i++) {
    Q = c * i;
    sum = sum + cordic_sin(Q) + cordic_cos(Q);
  }
  start = (millis() - start) / 1000.0f;
  Serial.print("sum = " + String(sum, 7) + ",\t  CORDIC_Time:" + String(start, 3) + "s\n");
  
  start = millis();
  sum = 0.0;
  for (int i = 1; i < N; i++) {
    Q = c * i;
    sum = sum + taylor_sin(Q) + taylor_cos(Q);
  }
  start = (millis() - start) / 1000.0f;
  Serial.print("sum = " + String(sum, 7) + ",\t  taylor_Time:" + String(start, 3) + "s\n");
  
  start = millis();
  sum = 0.0;
  for (int i = 1; i < N; i++) {
    Q = c * i;
    sum = sum + sin(Q) + cos(Q);
  }
  start = (millis() - start) / 1000.0f;
  Serial.print("sum = " + String(sum, 7) + ",\t  math.h_Time:" + String(start, 3) + "s\n");
}
Accuracy Test
Q = 0.1000
CORDIC: sin(Q) = 0.0998334, cos(Q) = 0.9950041
taylor: sin(Q) = 0.0998334, cos(Q) = 0.9950041
math.h: sin(Q) = 0.0998334, cos(Q) = 0.9950042
---------------------------------
Q = 0.2000
CORDIC: sin(Q) = 0.1986693, cos(Q) = 0.9800665
taylor: sin(Q) = 0.1986693, cos(Q) = 0.9800665
math.h: sin(Q) = 0.1986693, cos(Q) = 0.9800665
---------------------------------
Q = 0.3000
CORDIC: sin(Q) = 0.2955202, cos(Q) = 0.9553365
taylor: sin(Q) = 0.2955202, cos(Q) = 0.9553365
math.h: sin(Q) = 0.2955202, cos(Q) = 0.9553365
---------------------------------
Q = 0.4000
CORDIC: sin(Q) = 0.3894184, cos(Q) = 0.9210610
taylor: sin(Q) = 0.3894183, cos(Q) = 0.9210610
math.h: sin(Q) = 0.3894183, cos(Q) = 0.9210610
---------------------------------
Q = 0.5000
CORDIC: sin(Q) = 0.4794255, cos(Q) = 0.8775826
taylor: sin(Q) = 0.4794255, cos(Q) = 0.8775826
math.h: sin(Q) = 0.4794255, cos(Q) = 0.8775826
---------------------------------
Q = 0.6000
CORDIC: sin(Q) = 0.5646425, cos(Q) = 0.8253355
taylor: sin(Q) = 0.5646425, cos(Q) = 0.8253356
math.h: sin(Q) = 0.5646425, cos(Q) = 0.8253356
---------------------------------
Q = 0.7000
CORDIC: sin(Q) = 0.6442177, cos(Q) = 0.7648422
taylor: sin(Q) = 0.6442177, cos(Q) = 0.7648422
math.h: sin(Q) = 0.6442177, cos(Q) = 0.7648422
---------------------------------
Q = 0.8000
CORDIC: sin(Q) = 0.7173561, cos(Q) = 0.6967067
taylor: sin(Q) = 0.7173560, cos(Q) = 0.6967067
math.h: sin(Q) = 0.7173561, cos(Q) = 0.6967067
---------------------------------
Q = 0.9000
CORDIC: sin(Q) = 0.7833269, cos(Q) = 0.6216100
taylor: sin(Q) = 0.7833269, cos(Q) = 0.6216099
math.h: sin(Q) = 0.7833269, cos(Q) = 0.6216099
---------------------------------
Q = 1.0000
CORDIC: sin(Q) = 0.8414710, cos(Q) = 0.5403023
taylor: sin(Q) = 0.8414709, cos(Q) = 0.5403023
math.h: sin(Q) = 0.8414710, cos(Q) = 0.5403023
---------------------------------
Q = 1.1000
CORDIC: sin(Q) = 0.8912073, cos(Q) = 0.4535961
taylor: sin(Q) = 0.8912073, cos(Q) = 0.4535962
math.h: sin(Q) = 0.8912073, cos(Q) = 0.4535961
---------------------------------
Q = 1.2000
CORDIC: sin(Q) = 0.9320391, cos(Q) = 0.3623576
taylor: sin(Q) = 0.9320391, cos(Q) = 0.3623577
math.h: sin(Q) = 0.9320391, cos(Q) = 0.3623577
---------------------------------
Q = 1.3000
CORDIC: sin(Q) = 0.9635582, cos(Q) = 0.2674988
taylor: sin(Q) = 0.9635582, cos(Q) = 0.2674988
math.h: sin(Q) = 0.9635581, cos(Q) = 0.2674988
---------------------------------
Q = 1.4000
CORDIC: sin(Q) = 0.9854497, cos(Q) = 0.1699672
taylor: sin(Q) = 0.9854497, cos(Q) = 0.1699672
math.h: sin(Q) = 0.9854497, cos(Q) = 0.1699672
---------------------------------
Q = 1.5000
CORDIC: sin(Q) = 0.9974949, cos(Q) = 0.0707372
taylor: sin(Q) = 0.9974950, cos(Q) = 0.0707373
math.h: sin(Q) = 0.9974949, cos(Q) = 0.0707372
---------------------------------
Speed Test
sum = 73.2423320,	  CORDIC_Time:3.334s
sum = 73.2423170,	  taylor_Time:1.563s
sum = 73.2423780,	  math.h_Time:0.750s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值