C/C++实现三角函数的方法
前几天在超算学堂上用C语言做一个并行计算求函数积分的作业,恰好平台不支持math.h头文件,于是自己设计了两种计算三角函数的方法,在这里进行总结。
首先最容易想到的是利用泰勒展开式:
注意泰勒展开式的分母部分,要知道int的最大值为2147483647 < 13!,所以当n=6时就要结束累和,而此时由于泰勒展开式的收敛速度并不快,所以误差仍然很大(当x=8时,利用泰勒展开式实现的sinx与math库中自带sinx的绝对误差已经超过了200),因此不能使用泰勒展开式来实现三角函数。
在这里介绍一种相对精确度好很多的实现三角函数的方法——利用CORDIC算法,关于CORDIC算法的介绍详见这篇博客:http://blog.csdn.net/liyuanbhu/article/details/8458769
在这里以求sin(x)为例,主要利用的是直角坐标旋转的公式:
x' = cos(θ)*x - sin(θ)*y
y' = sin(θ)*x + cos(θ)*y
主要思路如下:给定一个弧度值a,函数从0开始,首先正向旋转π/4,直到旋转后的弧度值超过a,此时退回π/4,在继续正向旋转π/8,直到弧度值超过a,再退回π/8,再正向旋转π/16。。。如此循环直到旋转的弧度与a的误差小于一定值(下面代码中取π/16384),之后利用此时的x坐标和y坐标来计算出sin
算法的思路类似与二分查找,在实现算法时只需要知道特定几个弧度的三角函数值,就可以求出其它任意弧度的三角函数值,不存在溢出的问题,并且理论上精确度可以达到浮点数绝对值的最小值(精确度靠最终旋转弧度与a的误差和特定角度三角函数值的精确度决定)
由于最终我们要的只是坐标的比例,而不是精确的值,所以还可以上面的公式简化为(各项除以cos(θ)):
x' = x - tan(θ)*y
y' = tan(θ)*x + y
这样只需要知道特定角度的tan值就可以了,代码如下:
double pi = 3.1415926535897932;
double angle[] = {pi/4,pi/8,pi/16,pi/32,pi/64,pi/128,pi/256,pi/512,pi/1024,pi/2048,pi/4096,pi/8192,pi/16384};double tang[]={1,0.4142135623731,0.19891236737966,0.098491403357164,0.049126849769467,0.024548622108925,0.012272462379566,0.0061360001576234,0.0030679712014227,0.0015339819910887,0.00076699054434309,0.00038349521577144,0.00019174760083571};double sinx(double a){if(a <= (pi/16384)){return a; //因为a的值太小,sin a 约等于 a}else{//开始 CORDIC 算法bool negitive = a < 0; // sin(-a) = -sin(a)double x = 10;double y = 0;double theta = 0;for(int i = 0;i < 13;i ++){ //开始迭代double orix,oriy;while(theta < a){ //当前角度小于aorix = x;oriy = y;//坐标旋转x = orix - tang[i] * oriy;y = tang[i] * orix + oriy;theta += angle[i];}if(theta == a){if(negitive){return -(y/sqrt((x*x+y*y)));}else{return (y/sqrt((x*x+y*y)));}}else{//旋转的弧度超过了a,退回原来增加的角度,同时进入下一次迭代theta -= angle[i];x = orix;y = oriy;}}if(negitive){return -(y/sqrt((x*x+y*y)));}else{return (y/sqrt((x*x+y*y)));}}
}
该代码计算结果的精度可以达到10^-5次方,如果要提高精度,可以减小每次增加的弧度的最小值,例如将迭代每次增加的最小的弧度值设为 pi/65536
参考链接:
CORDIC算法入门:http://blog.csdn.net/liyuanbhu/article/details/8458769
CORDIC_百度百科:https://baike.baidu.com/item/CORDIC
C/C++实现三角函数的方法相关推荐
- 用正割对数计算积分的方法
用正割对数计算积分的方法 下面介绍一种利用正割对数,计算积分的方法. 相关资料下载网址: 链接:https://pan.baidu.com/s/1z3R9b-UmV3AcJKLPFNNT3A?pwd= ...
- Python中将弧度转换为角度和将角度转换为弧度的计算degrees() 、radians()方法
选择题 以下python代码输出什么? import math print(math.degrees(math.pi/2)) A 180.0 B 45.0 C 90.0 D 30.0 问题解析 1.m ...
- 计算机反三角函数如何求出分秒,【excel怎么输三角函数】请教高手:在Excel中能计算反三角函数arccos吗?如何计算?...
请教高手:在Excel中能计算反三角函数arccos吗?如何计算? 工具/材料:电脑.Excel. 第一步,打开电脑进入桌面开Excel制作如下所示的表格. 第二步,在F3单元格中输入弧度计算公式&q ...
- matlab三角多项式拟合,三角多项式拟合方法及地震数据处理
撰写目的和基本思路 撰写目的:基于地震数据光滑性较差的特征,以往拘泥于寻找地震数据数字特征等常规的统计分析方法局限性太大.为了反映地震数据统计规律的本质特征,提出三角多项式拟合方法. 基本思路:将所得 ...
- 用计算机算出90除以6.28,用计算器计算:sin51°30′+ cos49°50′-tan46°10′的值是 .——青夏教育精英家教网——...
题目所在试卷参考答案: 参考答案 一.基础.巩固达标 1.在Rt△ABC中,如果各边长度都扩大2倍,则锐角A的正弦值和余弦值( ) A.都没有变化 B.都扩大2倍 C.都缩小2倍 D.不能确定 思路解 ...
- 理解CSS3 transform中的Matrix(矩阵)
一.哥,我被你吓住了 打架的时候会被块头大的吓住,学习的时候会被奇怪名字吓住(如"拉普拉斯不等式").这与情感化设计本质一致:界面设计好会让人觉得这个软件好用! 所以,当看到上面& ...
- java 3number_java 数据Number、Math
一个初出茅庐的小子与大家共享一些关于Number和Math的使用,因水平有限,难免有写的不完善的地方,嘻嘻.看完之后,希望可以留下你珍贵的指导意见. The Numbers Classes 在写代码的 ...
- 【CSS3】 理解CSS3 transform中的Matrix(矩阵)
理解CSS3 transform中的Matrix(矩阵) by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu ...
- Java知多少(76)语言包(java.lang)简介
Java语言包(java.lang)定义了Java中的大多数基本类,由Java语言自动调用,不需要显示声明.该包中包含了Object类,Object类是整个类层次结构的根结点,同时还定义了基本数据类型 ...
最新文章
- [转] vim的复制粘贴小结
- js canvas游戏初级demo-上下左右移动
- python处理xml中非法字符的一种思路
- solaris UFS文件系统 要点
- 借助开源工具高效完成Java应用的运行分析
- 图像处理与识别技术的应用
- mysql 实体关系表_实体关系图
- 素数-试除法和埃式筛选法模板
- java poi excel 导入数据库_java POI 处理excel表格数据并导入数据库示例
- WebStorm中Node.js项目配置教程(1)——创建项目
- 软件质量与测试 黑盒测试
- Linux系统管理(9)——系统状态监控命令top使用详解
- 接口测试常用工具及测试方法(新手篇)
- 微服务框架自带uuid生成器
- 【代码片段分享】获取公历日期阴历日期二十四节气干支纪年传统节日Java版
- c语言中islower是什么函数,C语言中的isalpha,isdigit,islower,isupper等一系列函数...
- python安装外部模块Django
- 墙壁涂色问题--动态规划
- 天津大学计算机专硕_天津大学计算机学院学硕和专硕哪个好?
- EXCL模板报盘数据导入