社区
数据结构与算法
帖子详情
如何快速且高精度地求sin函数?
LyndonZheng
2006-09-14 12:40:14
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
...全文
3727
50
打赏
收藏
如何快速且高精度地求sin函数?
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
50 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
LyndonZheng
2006-09-20
打赏
举报
回复
呵呵,今天搞电了,精度速度空间都可以,结贴了!特别鸣谢疯狂懒猪~亲一下~~~
crazy_lazy_pig
2006-09-19
打赏
举报
回复
呵呵, 我回贴, 有的时候是为了分, 但是楼主却总是不结贴. 而有的时候不是为了分, 却总能得到楼主的贡献.
像这一贴, 我如果不来关心, 就不知道天底下还有个cordic算法, 回了贴, 也学到了东西, 说实在的, 我是应该给人家分的, 哪里还奢求别人给我分啊.
LyndonZheng
2006-09-19
打赏
举报
回复
我发之前那一贴时还未看你的贴,所以才那样问,呵呵~~~
差不多可以结贴了,可惜只有50分,觉得对不起大家:(
crazy_lazy_pig
2006-09-18
打赏
举报
回复
好像楼主还是比较关心我求sinx的方法, 其实, 我是用数学软件算的, 要几个有效数字就能有几个. 我给你的这些数值请放心使用, 足够安全(就是cos(arctan(1/2^50))的值有点奇怪, 不过这并不影响我们的使用).
crazy_lazy_pig
2006-09-18
打赏
举报
回复
以楼主的精度要求, 45次分解足够多了, 下面给出 j=0到50 的arctan(1/2^j)的弧度值(15位有效数字):
[.785398163397448, .463647609000806, .244978663126864,
.124354994546761, .624188099959573e-1, .312398334302683e-1,
.156237286204768e-1, .781234106010111e-2, .390623013196697e-2,
.195312251647882e-2, .976562189559319e-3, .488281211194898e-3,
.244140620149362e-3, .122070311893670e-3, .610351561742088e-4,
.305175781155261e-4, .152587890613158e-4, .762939453110197e-5,
.381469726560650e-5, .190734863281019e-5, .953674316405961e-6,
.476837158203089e-6, .238418579101557e-6, .119209289550780e-6,
.596046447753905e-7, .298023223876953e-7, .149011611938477e-7,
.745058059692383e-8, .372529029846191e-8, .186264514923096e-8,
.931322574615479e-9, .465661287307739e-9, .232830643653870e-9,
.116415321826935e-9, .582076609134674e-10, .291038304567337e-10,
.145519152283669e-10, .727595761418343e-11, .363797880709171e-11,
.181898940354586e-11, .909494701772928e-12, .454747350886464e-12,
.227373675443232e-12, .113686837721616e-12, .568434188608080e-13,
.284217094304040e-13, .142108547152020e-13, .710542735760100e-14,
.355271367880050e-14, .177635683940025e-14, .888178419700125e-15]
以及相对应的角度值:
[45.0000000000000, 26.5650511770779, 14.0362434679265,
7.12501634890177, 3.57633437499734, 1.78991060824607,
.895173710211074, .447614170860553, .223810500368538,
.111905677066207, .559528918938038e-1, .279764526170038e-1,
.139882271422650e-1, .699411367535292e-2, .349705685070401e-2,
.174852842698045e-2, .874264213693784e-3, .437132106872336e-3,
.218566053439348e-3, .109283026720072e-3, .546415133600855e-4,
.273207566800490e-4, .136603783400252e-4, .683018917001269e-5,
.341509458500636e-5, .170754729250319e-5, .853773646251596e-6,
.426886823125798e-6, .213443411562898e-6, .106721705781449e-6,
.533608528907246e-7, .266804264453623e-7, .133402132226812e-7,
.667010661134060e-8, .333505330567029e-8, .166752665283514e-8,
.833763326417575e-9, .416881663208788e-9, .208440831604394e-9,
.104220415802197e-9, .521102079010984e-10, .260551039505492e-10,
.130275519752746e-10, .651377598763729e-11, .325688799381865e-11,
.162844399690932e-11, .814221998454661e-12, .407110999227331e-12,
.203555499613664e-12, .101777749806833e-12, .508888749034163e-13]
还有其cos值:
[.707106781186550, .894427190999916, .970142500145332,
.992277876713667, .998052578482889, .999512076087081,
.999877952034693, .999969483818786, .999992370692778,
.999998092656822, .999999523163180, .999999880790732,
.999999970197680, .999999992549423, .999999998137356,
.999999999534336, .999999999883586, .999999999970898,
.999999999992723, .999999999998181, .999999999999549,
.999999999999888, .999999999999972, .999999999999997,
.999999999999996, .999999999999996, 1.00000000000000,
1.00000000000000, .999999999999999, 1.00000000000000,
1.00000000000000, .999999999999999, 1.00000000000000,
1.00000000000000, .999999999999996, 1.00000000000000,
1.00000000000000, 1.00000000000000, .999999999999999,
.999999999999999, 1.00000000000000, 1.00000000000000,
1.00000000000000, 1.00000000000000, 1.00000000000000,
1.00000000000000, 1.00000000000000, 1.00000000000000,
1.00000000000000, 1.00000000000000, .999999999999996]
crazy_lazy_pig
2006-09-18
打赏
举报
回复
cordic算法其实跟我的算法差不多. 也是把角度分解, 但是分解的方法跟我不一样, 它是用一种类似于二分法的逼近思路, 有可能分解的比我多, 但是分解后就不需要乘法计算了. 具体分解法如下:
仍然假设角theta位于0到90度之间, 首先我们把直角平分, 得到一个45度的角( tan45=1=2^0 ), 那么alfa要么在平分线上方, 要么就在下方, 若在上方, 则作从平分线开始向上作一个角, 使得其tan=1/2=2^(-1), 否则向下做该角, 这样角theta必在新作出来的线上或者线下, 继续如上法作角, 使tan=1/4=2^(-2), 如此一直做下去, 我们就得到一组线, 该线的极限就是 theta 角. 这样我们就得到了 theta的一个分解(有可能是无穷的):
theta=alfa0 + delta1*alfa1 + delta2*alfa2 + ... + deltaj * alfaj +... ,
其中tan(alfaj)=2^(-j) , delta=-1 或者 +1, 在向上作角时其值为正1 , 向下时为 -1 .
和差化积公式:
sin( x + alfaj ) = cos(x)*sin(alfaj) + sin(x)*cos(alfaj)
= ( sin(x) + cos(x)*tan(alfaj) ) * cos(alfaj)
cos( x + alfaj ) = cos(x)*cos(alfaj) + sin(x)*sin(alfaj)
= ( cos(x) - sin(x)*tan(alfaj) ) * cos(alfaj)
现令:
s[j+1] = s[j] + c[j] * tan(deltaj*alfaj) = s[j] + deltaj*c[j]*(2^(-j)) = s[j]+deltaj*c[j]>>j
c[j+1] = c[j] - s[j] * tan(deltaj*alfaj) = c[j] - deltaj*s[j]*(2^(-j)) = c[j]-deltaj*s[j]>>j
这其中alfaj为上面我们谈到的theta的分解项, s[j],c[j]分别类似于sin( alfa0 + ... + alfaj ),cos( alfa0 + ... + alfaj ), 但是, 对照上面的和差化积公式, 我们应该发现, 在每次转化的时候, 我们都少乘了一个系数:cos(alfaj). 因此sqrt(s[j+1]*s[j+1] + c[j+1]*c[j+1]) = sqrt(s[j]*s[j] + c[j]*c[j])/cos(alfaj), 即
s[j]*(cos(alfa0*...*cos(alfaj-1))=sin(alfa0+...+alfaj)
这样我们通过若干次移位运算和加法(减法), 就可以得到sin(theta)的一个放大了的值, 再除以一个放大系数cos(alfa0*...*cos(alfaj-1)就可以了(这里似乎是要乘法运算了).
下面的关键就是求theta的分解式了, 即确定delta的值(注意, alfaj的值是确定的). 为此我们需要事先建立一个表: alfa[N] 来存放alfaj的值, 使其满足: tan( alfa[j] ) = 2^(-j),且tan(alfa[N-1])<e (e为你所需的精度). 我们令 t[0] = theta, delta[0]=1.
t[j+1]=t[j]-alfa[j]*delta[j], 若t[j+1]<0, 则delta[j+1]=-1, 否则delta[j+1]=1
另外cos(alfaj)可以由tan(alfaj)=2^(-1) 求得, 如果这里仍然不想作乘法, 那么索性再做个表.
最后总结一下求解过程:
while( t[j+1]=t[j]-alfa[j]*delta[j] == 0 ){
delta[j+1]=sgn(t[j+1]);
s[j+1] = s[j]+delta[j]*c[j]>>j;
c[j+1] = c[j]-delta[j]*s[j]>>j;
j++
}
s[j]*=cos(alfa0)*cos(alfa1)*...*cos(alfaj);//注意这是伪代码或许有错
crazy_lazy_pig
2006-09-18
打赏
举报
回复
对了, 忘了精度问题了, 又计算了一下, 在j>20时, tan(1/2^j)=1/2^j, 所以第一个表存贮20个值就足够了.
这样加上那些cos大概需要四十多个存贮空间, 可以把我原来算法的空间占用率减半, 不知道还大不大了?
crazy_lazy_pig
2006-09-18
打赏
举报
回复
计算器是怎么做出来的?
=========================
这个问题我也不知道, 得问计算的设计者
说误差是1/(2的-12次方)?
=========================
不知道楼主看的是什么资料, 我不认为它是这么精度, 精度完全是人定的, 一个算法怎么能有确定的精度呢? 如果有, 那么它肯定是不好的. 也许你看的算法说的这个精度是在最后一步的取值上, 我看的一个材料中是直接将其取成0.678(记不清楚了, 反正是个固定值)而不是若干个cos的乘积, 这样做当然是误差比较大的, 但是, 即使是这样, 它仍然能保证精度在1/(2的-12次方), 可见其算法的高精度.
不知道楼主是否看懂了我的回贴, 我贴出的算法是可以精确到任意精度的, 按照我给你的数字计算的话, 则可以达到15位有效数字, 且最多花费80个固定存贮单元.
LyndonZheng
2006-09-18
打赏
举报
回复
看了一下cordic算法的资料,说误差是1/(2的-12次方),是否属实?如果真的是这样的话这个算法还是不可取哦~~~
AFIC
2006-09-18
打赏
举报
回复
MARK
caoze
2006-09-18
打赏
举报
回复
计算器是怎么做出来的?
LyndonZheng
2006-09-17
打赏
举报
回复
回Polaris_()
我对你的算法非常之感兴趣.感谢你的指教~~我的qq是723956048 名称叫san。
油箱是san_77227487@163.com
waiting for you~~Thank you!
另外有一点可能忘了说,向大家说声不好意思先:(
就是乘法是用13位十进制数(13个nipple)进行相乘然后取12位的,一些多数位设备可以运算的算法在这里应该不可用,比如说tailor级数。具体怎样不可用我也说不清,是boss说他们以前用过tailor,但失败了。
LyndonZheng
2006-09-17
打赏
举报
回复
回疯狂的猪
你的方法确实可行,而且我现在正在完善中。不过我的方法有点不同,我是用一种逼近法求出0到1度的sin值,再用另一种逼近方法求出cos值。为什么要求出cos呢?因为角相加需要用到。不知道你是用什么办法可以通过x求出sinx并精确到12位呢?我的逼近法用了8次乘法,再用6次乘法求出cos。另,把1度至90度的sin值和cos值都保存进去需要0.6k个nipple,我老板说太大了。:< 你有没好的对策?等待你的回复,谢谢~~我的邮箱是san_77227487@163.com
crystalshark
2006-09-17
打赏
举报
回复
可以考虑用硬件搭
否则,我想用空间换时间的方案应该可行
kmlxk0
2006-09-17
打赏
举报
回复
仰望一下
llmice
2006-09-17
打赏
举报
回复
复杂,高级,顶。。。。
lifehot
2006-09-17
打赏
举报
回复
up...........................
Joyfish
2006-09-17
打赏
举报
回复
mark
LyndonZheng
2006-09-17
打赏
举报
回复
cordic algorithm的确是个好办法,研究中。。。。
已经懂了的达人可以指教一下吗?不胜感激!
hawk234
2006-09-16
打赏
举报
回复
up
加载更多回复(28)
c语言三角
函数
精度不够,
快速
三角
函数
算法的误差控制(
sin
cos)
工程应用常涉及三角
函数
的
快速
计算。设计者往往需要降低运算精度以提高程序的运行速度。常用的
快速
三角
函数
算法主要包括CORDIC、泰勒展开式逼近、查表等等。然而,网上的文章大多只介绍如何实现相应的算法,而忽视了定量分析算法精度并以此指导设计的过程。此外,算法不同,误差分析的数学方法也不尽相同。在多种算法之间比较时,需要耗费一些时间来建立模型。如果建立一个通用的误差分析框架,框架不局限于现存的几类算法,...
用泰勒公式编写一个
sin
函数
--C语言
通过麦格劳林展开式,来编写一个
sin
函数
,C语言内置了三角
函数
,这个三角
函数
在 #include<math.h> 的头文件下要输入角度数,是有着需要先将角度转化为弧度在进行使用,我编写的
sin
函数
当精度太高时高角度数会无法执行,可能存在数据溢出 //
sin
.cpp :
sin
x=x-x*x*x/3*2+x*x*x*x*x/5*4*3*2-... #include "st...
Python实现:计算
sin
函数
的算法及源码
在Python中,使用math库中的
sin
函数
可以计算出给定角度的正弦值。本文介绍一种基于泰勒级数的方法来计算
sin
函数
的算法,同时提供完整源码。该
函数
使用for循环来计算泰勒级数展开式中每一项的和,其中系数为((-1)^n),即正项负项交替出现。总结来说,本文介绍了一种使用泰勒级数展开式来计算正弦
函数
的算法,并提供了完整的Python源码实现。根据以上公式,我们可以编写一个计算
sin
函数
的
函数
,其输入参数为角度,返回值为正弦值。其中,余项Rn的绝对值小于等于x^(2n+2)/(2n+2)!
C#中提高三角
函数
计算精度
版本:VS2008 C# 作者:xmwang 方法一:三角
函数
分解计算提升精度 C#中Math.
Sin
进行三角
函数
计算,输入参数必须为double型,double型的有效位数相对decimal的28位要小很多,笔者认为可以将decimal类型分解为多个double类型进行三角
函数
计算,比如:
Sin
(decimalData)=
Sin
(doubleData1 + doubleData2)= ...
【雕爷学编程】Arduino 手册之三角
函数
sin
()
sin
() 是 Arduino 数学库中的一个
函数
,它的作用是计算一个角度的正弦值。Arduino 2005 年时面世,作为意大利伊夫雷亚地区伊夫雷亚互动设计研究所的学生设计,目的是为新手和专业人员提供一种低成本且简单的方法,以建立使用传感器与环境相互作用的装置。可以使用
sin
()
函数
和反正弦
函数
a
sin
() 来计算每秒钟物体沿着圆周移动的弧长对应的弧度值,然后除以 PI 得到相对于圆心的角度变化。在使用
sin
()
函数
计算角度的正弦值时,确保输入的角度值在正确的范围内。
数据结构与算法
33,008
社区成员
35,326
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章