社区
数据结构与算法
帖子详情
如何快速且高精度地求sin函数?
LyndonZheng
2006-09-14 12:40:14
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
...全文
4009
50
打赏
收藏
如何快速且高精度地求sin函数?
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
复制链接
扫一扫
分享
转发到动态
举报
AI
作业
写回复
配置赞助广告
用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/C++
sin
函数
算法详解及源码
sin
函数
算法主要有两种实现方式:泰勒级数展开和查表法。泰勒级数展开是将
sin
函数
表示为一系列无限项的和,通过截断级数项的方式来逼近真实的
sin
函数
值。查表法则是将一段特定范围的
sin
函数
值预先计算好并存储在一个查找表中,然后通过查表的方式来获取
sin
函数
值。
sin
函数
是三角
函数
之一,它表示某个角的正弦值。在数学中,正弦值被定义为一个直角三角形中对边与斜边的比值。
Python
sin
函数
算法详解及源码
sin
函数
算法是计算三角
函数
sin
(x)的方法。计算
sin
函数
值:
sin
(x) = radians - (radians^3 / 3!计算
sin
函数
值:
sin
(x) = radians - (radians^3 / 3!计算
sin
函数
值:
sin
(x) = radians - (radians^3 / 3!计算
sin
函数
值:
sin
(x) = radians - (radians^3 / 3!计算
sin
函数
值:
sin
(x) = radians - (radians^3 / 3!
计算
sin
函数
的算法实现
但是,如果我们想了解
sin
函数
的实现原理,或者想自己编写一个
sin
函数
的近似算法,那么我们可以使用泰勒级数展开来逼近
sin
函数
。这是因为我们使用了泰勒级数展开来逼近
sin
函数
,而级数是无穷的,所以我们只能计算到一定的精度。如果你需要更
高精度
的计算,或者处理更复杂的数学问题,建议直接使用Python内置的math模块中的
sin
函数
。循环的条件是当前项的绝对值大于一个很小的数(这里使用1e-10作为阈值),以保证计算的精度。泰勒级数是一种用于近似
函数
的方法,它将一个
函数
表示为无穷级数的形式。
c语言三角
函数
精度不够,
快速
三角
函数
算法的误差控制(
sin
cos)
工程应用常涉及三角
函数
的
快速
计算。设计者往往需要降低运算精度以提高程序的运行速度。常用的
快速
三角
函数
算法主要包括CORDIC、泰勒展开式逼近、查表等等。然而,网上的文章大多只介绍如何实现相应的算法,而忽视了定量分析算法精度并以此指导设计的过程。此外,算法不同,误差分析的数学方法也不尽相同。在多种算法之间比较时,需要耗费一些时间来建立模型。如果建立一个通用的误差分析框架,框架不局限于现存的几类算法,...
C语言实现
sin
函数
(附带源码)
本项目旨在实现一个简单的
sin
(x)
函数
,使用 泰勒级数 (Taylor Series)展开来近似计算
sin
(x) 的值。
sin
(x) 是三角
函数
之一,广泛应用于数学、物理、工程等领域。通过泰勒级数,我们能够通过一系列的加法和乘法运算来逼近
sin
(x) 的值,通常这种方法适用于计算机中无法直接实现的数学
函数
。
数据结构与算法
33,028
社区成员
35,336
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章