独闷闷网

 找回密码
 立即注册
搜索
查看: 2532|回复: 0
打印 上一主题 下一主题
收起左侧

[原创] 一种不需要引入“long类型的中间变量”的处理算法溢出的办法。

[复制链接]
跳转到指定楼层
楼主
发表于 2016-10-2 09:01:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 jianhong_wu 于 2016-10-4 09:47 编辑

★坚鸿-深圳:

【意外溢出。】

      运算过程中的意外溢出,稍不注意,就中招,不信,请看下面的例子(在keil C51编译器环境下):
  1.     /*---C语言学习区域的开始。-----------------------------------------------*/
  2.     unsigned long  a=0;
  3.     unsigned int x=1000;
  4.     unsigned int y=3000;
  5.     void main() //主函数
  6.     {
  7.        a=x*y;    //猜猜a是多大?
  8.        View(a);  //把第1个数a发送到电脑端的串口助手软件上观察。
  9.        while(1)  
  10.        {
  11.        }
  12.     }
  13.     /*---C语言学习区域的结束。-----------------------------------------------*/
复制代码

     猜猜a是多大?很多人以为理所当然3000000,但是实际上是50880!中招了吧。莫名其妙的50880,就是因为意外溢出所致。怎么办呢?请看下面介绍的两种解决办法。

【第一种办法:引入中间变量。】

       我以前曾多次说过“为了避免运算过程中的意外溢出,建议大家把所有参与运算的变量都用unsigned long类型的变量,如果不是unsigned long类型的变量,就引入unsigned long类型的中间变量。”这种老方法如下:
  1.     /*---C语言学习区域的开始。-----------------------------------------------*/
  2.     unsigned long  a=0;
  3.     unsigned int x=1000;
  4.     unsigned int y=3000;
  5.     unsigned long  s; //引入的unsigned long中间变量。
  6.     unsigned long  t; //引入的unsigned long中间变量。
  7.     void main() //主函数
  8.     {
  9.        s=x;  //先把变量的数值搬到unsigned long中间变量。
  10.        t=y;   //先把变量的数值搬到unsigned long中间变量。
  11.        a=s*t;    //中间变量代表原始变量进行运算。
  12.        View(a);  //把第1个数a发送到电脑端的串口助手软件上观察。
  13.        while(1)  
  14.        {
  15.        }
  16.     }
  17.     /*---C语言学习区域的结束。-----------------------------------------------*/
复制代码

     这一次,运算结果是正确的3000000。
     现在反省了一下,这种办法虽然可靠实用,但是显得有点罗嗦,而且引入的中间变量也无形中增加了一点内存。还有没有更好的办法?请看下面介绍的第二种办法。

【 第二种办法:C语言的类型强制转换。】

       括号在C语言中有强制的意思,可以强制改变优先级,也可以临时强制改变运算过程中的变量类型。在运算过程中临时强制改变类型变量,就可以省去额外引入的中间变量,这种方法相比上面第一种老办法确实更便捷灵活。
  1. /*---C语言学习区域的开始。-----------------------------------------------*/
  2. unsigned long  a=0;
  3. unsigned int x=1000;
  4. unsigned int y=3000;
  5. void main() //主函数
  6. {
  7.      a=(unsigned long)x*(unsigned long)y;  //添加的两个括号就是类型的强制转换。
  8.      View(a);  //把第1个数a发送到电脑端的串口助手软件上观察。
  9.      while(1)  
  10.      {
  11.      }
  12. }
  13. /*---C语言学习区域的结束。-----------------------------------------------*/
复制代码

      这一次,运算结果也是正确的3000000。

       多说一句,除了上述的乘法运算之外,其它的加、减、除法运算适不适用呢?虽然我还没有逐个测试,但是我感觉应该是都适用的。因此,在“加、减、除”等运算中,在必要的时候,也要在相关的变量的前缀加上类型的强制转换。



乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-4-28 12:05 , Processed in 0.149799 second(s), 17 queries .

快速回复 返回顶部 返回列表