社区
数据结构与算法
帖子详情
如何快速且高精度地求sin函数?
LyndonZheng
2006-09-14 12:40:14
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
...全文
4027
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
函数
是三角
函数
之一,它表示某个角的正弦值。在数学中,正弦值被定义为一个直角三角形中对边与斜边的比值。
计算
sin
函数
的算法实现
但是,如果我们想了解
sin
函数
的实现原理,或者想自己编写一个
sin
函数
的近似算法,那么我们可以使用泰勒级数展开来逼近
sin
函数
。这是因为我们使用了泰勒级数展开来逼近
sin
函数
,而级数是无穷的,所以我们只能计算到一定的精度。如果你需要更
高精度
的计算,或者处理更复杂的数学问题,建议直接使用Python内置的math模块中的
sin
函数
。循环的条件是当前项的绝对值大于一个很小的数(这里使用1e-10作为阈值),以保证计算的精度。泰勒级数是一种用于近似
函数
的方法,它将一个
函数
表示为无穷级数的形式。
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!
c语言三角
函数
精度不够,
快速
三角
函数
算法的误差控制(
sin
cos)
工程应用常涉及三角
函数
的
快速
计算。设计者往往需要降低运算精度以提高程序的运行速度。常用的
快速
三角
函数
算法主要包括CORDIC、泰勒展开式逼近、查表等等。然而,网上的文章大多只介绍如何实现相应的算法,而忽视了定量分析算法精度并以此指导设计的过程。此外,算法不同,误差分析的数学方法也不尽相同。在多种算法之间比较时,需要耗费一些时间来建立模型。如果建立一个通用的误差分析框架,框架不局限于现存的几类算法,...
C语言
sin
函数
使用教程
sin
函数
是C语言数学库中的一个基础
函数
,用于计算一个角度的正弦值。正弦
函数
是三角
函数
的一种,广泛应用于工程、物理、信号处理等众多科学计算领域。在直角三角形中,正弦值定义为对边与斜边的比值。而在单位圆上,正弦值表示的是圆上一点的y坐标值。数学上,正弦
函数
是周期
函数
,具有周期为2π的特性,意味着每个2π的间隔,
函数
值会重复出现。此外,正弦
函数
也是奇
函数
,即满足
sin
(-x) = -
sin
(x)的性质。这些数学特性使得正弦
函数
在周期性波动现象的建模中非常有用。
数据结构与算法
33,027
社区成员
35,336
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章