有这么一个
计算公式:
PHA_adj=65536-18919*(T_Pimp-time_cnt)/time_cnt;
其中:
PHA_adj:unsignedint
T_Pimp:常数,等于3266
time_cnt:unsignedint范围在2000至3000之间
这个公式有错吗,如果错了错在哪?怎么改才能算出期望值?
(KEILC518位机等同于8052)PHA_adj结果精度需保证在0.1%内
呵呵答案在后面给出.
网友评论:分开之后发觉,那个INT×INT后,INT是放不下结果的。
网友评论:直接开长整型数据定义
网友评论:PHA_adj=~((unsignedlong)18919*(T_Pimp-time_cnt)/time_cnt)+1;
不如:
PHA_adj=65536-(unsignedlong)18919*(T_Pimp-time_cnt)/time_cnt;好
为什么呢,什么原因呢
网友评论:很烦强制转换,那玩意很多时候是个隐性炸弹。。。
直接开长整型数据定义
答:直接开长整型定义会带来如下后果:
占用数据存储器多,代码长,执行时间长.
28楼:楼主所说的好是什么方面的??
25楼:
PHA_adj=~((unsignedlong)18919*(T_Pimp-time_cnt)/time_cnt)+1;
不如:
PHA_adj=65536-(unsignedlong)18919*(T_Pimp-time_cnt)/time_cnt;好
为什么呢,什么原因呢
答:PHA_adj=65536-(unsignedlong)18919*(T_Pimp-time_cnt)/time_cnt;代码比较少一点.
网友评论:答楼上两位
27楼:很烦强制转换,那玩意很多时候是个隐性炸弹。。。
直接开长整型数据定义
答:直接开长整型定义会带来如下后果:
占用数据存储器多,代码长,执行时间长.
-------------------------------------------------------------
且,你以为你没开长整型,代码就短了?执行时间就短了?至于占用RAM多的问题,你开成局部变量就是了,用完自动被编译器释放了。
网友评论:且。。。
xuehongren发表于2008-10-2410:43侃单片机←返回版面
29楼:答楼上两位
27楼:很烦强制转换,那玩意很多时候是个隐性炸弹。。。
直接开长整型数据定义
答:直接开长整型定义会带来如下后果:
占用数据存储器多,代码长,执行时间长.
-------------------------------------------------------------
且,你以为你没开长整型,代码就短了?执行时间就短了?至于占用RAM多的问题,你开成局部变量就是了,用完自动被编译器释放了。
没必要得整成长整型吧,照你这么说,那只要牵扯到LONGINT的都定义成LONGINT?
至于你说的隐性炸弹应该是可以避免的
网友评论:(unsignedlong)18919=18919L
65536-x=取补码(~x)+1,且不牵涉进位。
17L前面的65536没加L或(unsignedlong)
刚才试了下,(unsignedlong)18919写成18919L确实没问题,但不知道其它是否也有如此简写:
如:,(unsignedint)189等
网友评论:一个A人的说法~~~
网友评论:有哪位能给鄙人推荐一本好的C51方面的书啊
网友评论:所长的程序对,但是精度降低了。
网友评论:我记得我也做过这样的事情,不过没关心什么,用double就行了,当然程序是长了点,资源也占多点,但我精度有了保证。
网友评论:同意扩展数据类型的长度
我记得我也做过这样的事情,不过没关心什么,用double就行了,当然程序是长了点,资源也占多点,但我精度有了保证。
对数据类型的定义应该还是满足要求就行,如这个问题,产品需要的精度为小于等于0.1%,所以就只需转成LONGINT就行了,计算也不会产生溢出错误
网友评论:我在程序内从未用过小数,为我觉得一切小数在单片机里都是以二进制整数来实现的,不知各位的理解。
网友评论:65536L-18919L*(T_Pimp-time_cnt)/time_cnt
=65536-18919L*(T_Pimp-time_cnt)/time_cnt
网友评论:大家就顶顶吧
网友评论:顶一下吧
网友评论:因为C51的编译器默然的整型为16位,所以对于小于32768的数就会认为是整型,做16位的运算,
对于运算结果超出16位的,就被截断了。如果运算结果最高位为1的,还要进行符号扩展,例如
如果你写的是j=20000*2;,结果就是0xFFFF9C40了。对于大于等于32768的数,就会先自动扩展为
longint型,然后再运算,这时结果就不会出错了,为了安全起见,不管它多大,还是明确指定为好:
j=20000L*4;
j=20000L*2;
j=65535L*4;
如果你换成keilCARM,就不会存在这个问题了,因为ARM是32位的,int就是32位的。
网友评论:你的解释我再验证下,不过先感谢你了.
网友评论:保留整数,省掉小数.
网友评论:飘过
网友评论:8位的类似89C52
网友评论:应该是溢出。
网友评论:PHA_adj=84455-(unsignedlong)18918*T_Pimg/time_cnt;
网友评论:要建立“数值与类型相互独立”的概念
常数是有类型的,某些数值有默认类型,那只能当作特例
数学等价变换:
65536-18919*(T_Pimp-time_cnt)/time_cnt
=65536-(18919*(T_Pimp/time_cnt-1))
=65536-(18919*(T_Pimp/time_cnt)-18919)
=84455-18919*(T_Pimp/time_cnt)
C语言表达式:
84455uL-(18919uL*T_Pimp)/time_cnt
网友评论:PHA_adj=65536-(unsignedlong)(18919*(T_Pimp-time_cnt))/(unsignedlong)time_cnt;
网友评论:PHA_adj=65536-((unsignedlong)18919*(T_Pimp-time_cnt))/(unsignedlong)time_cnt;
对有的编译器,17楼的能过。
网友评论:应该是对所有编译器17楼都能过吧
网友评论:对于32位变量和16位变量的运算,如果不强制类型转换有的向16位看齐,有的向32位看齐,我的印象是IARforMSP430向16位看齐,而IARforARM却向32位看齐,是不是对于片内RAM资源少的倾向节省RAM,而对片内RAM资源多的倾向浪费RAM,也许是由IAR的配置确定。16位变量和8位变量的运算也是这样
网友评论:我只看到了谭浩强老师书上说的,不同数据类型之间的混合运算,都是短字节数向长字节数对齐.
网友评论:谭浩强老师书上说的曾让我困惑了很久,这个世界没有绝对的权威。
网友评论:是的他的书有些写得也不全面,不过他的书还是写得很好的.
网友评论:aa
网友评论:qqqqqqqqqqqqqq
网友评论:unsignedlongsum;
sum=T_Pimp-time_cnt;
sum=18919*sum;
sum=sum/time_cnt;
PHA_adj=65536-(unsignedint)sum;
网友评论:楼上的方法也可以啰不过这样写有点麻烦.
网友评论:PHA_adj=(unsignedint)(65536-18919.0*(T_Pimp-time_cnt)/(1.0*time_cnt));
先做成浮点数,再转换为int
网友评论:楼上的你的结果没错,但不是最好的处理办法.
网友评论:18919.0的出现,乘法就变成了浮点数乘法,代码增加不少.
网友评论:如果实在32系统里,这个公式是不会溢出的,但如果在int为16位的系统里,这个公式确实会溢出。还有你也没有说清楚要求的精度要求,当精度要求比较高时,该公式必须转换成浮点类型进行计算
网友评论:在KEIL的C51编译unsignedint最大0XFFFF
18919*(T_Pimp-time_cnt)一定溢出了,
但ARM中unsignedint最大0XFFFFFFFF,结果没问题
网友评论:我的是8位的MCU呢相当于80C52.
网友评论:不过,楼主的问题有点小儿科了。
类似程序编译验证一下,马上可以得出结果正确与否。
这问题拿不出台面的,不用分享了。
网友评论:我问了下用C做了几年产品的同事,他居然还找不到BUG,呵呵,我的目的是让新手增加点经验.
网友评论:如果换编译器,这些数学计算还是要重新确认一次.
另外,还是要注意边界测算.我的方法也是数据扩展,但绝对不转浮点。
网友评论:毕业后二十年了,总算接了个大工程,造一根三十米烟囱,工期两个月,造价三十万,不过要垫资。总算在上个月底搞完了。今天人家去验收,被人骂得要死,还没有钱拿。妈的!图纸看反了,人家是要挖一口井!
网友评论:还是把整型写明白好,2字节的就定义成短整型,4字节的就定义成长整型,勉得各个系统不一样.
网友评论:如果不是就事论事,光一个式子,哪有错对可论的。
所谓错者,指那个结果与期望的不一致。楼主得先给一个样品值与使用环境,才能评论错那里了。
网友评论:答案前面已经有人说了啊