社区
数据结构与算法
帖子详情
如何快速且高精度地求sin函数?
LyndonZheng
2006-09-14 12:40:14
在一块容量速度都很一般的芯片上运行,浮点数乘法不能超过20次,运算用12位运算,但精度达到12位。上网查过一些方法,速度和精度不能同时达到要求,哪位大哥有好方法介绍一下?谢谢~~
...全文
4162
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)
Unable to start EmbeddedWebApplicationContext due to mis
sin
g EmbeddedServletContainerFactory bean
There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quickly.
Unable to start EmbeddedWebApplicationContext due to mis
sin
g EmbeddedServletContainerFactory bean.
自己新建的Maven 项目,然后通过修改 pom.xml 转为 Spring Boot 项目,出现此问题。启动日志如下:org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context
热部署Unable to start EmbeddedWebApplicationContext due to mis
sin
g EmbeddedServletContainerFactory bean
一文带你认识热部署、附实验结果 本文所诉热部署不包含前端,仅对服务端的一些热部署做些简要说明! 热部署 每次修改代码(以及修改配置文件)都要重启,是不是很烦、讲真你的服务涉及第三方服务过多时、要加载时初始化一些数据的时候,你搞热部署也不见得能省多少时间,但是你可以配置下其他目录exclude! 原理 使用了两个ClassLoader,一个(base ClassLoader)加载不会改变的类(依赖的jar包)、exclude的目录等。另一个restart ClassLoader 加载会更改的文.
数据结构与算法
33,026
社区成员
35,334
社区内容
发帖
与我相关
我的任务
数据结构与算法
数据结构与算法相关内容讨论专区
复制链接
扫一扫
分享
社区描述
数据结构与算法相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章