在线情况
楼主
  • 头像
  • 级别
    • 积分8
    • 经验8471
    • 文章102
    • 注册2008-04-20
    讨论一个乘法数学运算式与编译器处理问题
    我的数学运算是为 (3985/4095)*2.5
    答案算出来为0,好奇怪,我改成下面的样式还是不行,都是0
    long aa;
    aa= (long)3985/(long)4095*(long)2.5;

    我使用的是f449(硬件乘法器有开没开都一样)
    [ 此贴最后由DC在2008-8-3 17:23:20编辑过 ]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
      • 积分51
      • 经验2657
      • 文章206
      • 注册2007-03-18
      你这个问题我没有试过,因为我总是尽量避免出现这样的运算,大多数情况下,我会变成这样的方法来写:
      long aa;
      aa = 4985 * 25 / 4095 / 10;
      我写这种式子的原则就是,式中参数不带小数,先乘后除,注意防止溢出。
      微控论坛特约嘉宾
      在线情况
      3
      • 头像
      • 级别
        • 积分8
        • 经验8471
        • 文章102
        • 注册2008-04-20
        [QUOTE][B]下面引用由[U]hwdz[/U]发表的内容:[/B]

        你这个问题我没有试过,因为我总是尽量避免出现这样的运算,大多数情况下,我会变成这样的方法来写:
        long aa;
        aa = 4985 * 25 / 4095 / 10;
        我写这种式子的原则就是,...[/QUOTE]

        我改成你的方式就出現
        Warning[Pe061]: integer operation result is out of range
        微控网感谢您的参与
        在线情况
        4
        • 头像
        • 级别
          • 积分51
          • 经验2657
          • 文章206
          • 注册2007-03-18
          哦?莫非不支持long型变量了?
          微控论坛特约嘉宾
          在线情况
          5
          • 头像
          • 级别
            • 积分8
            • 经验8471
            • 文章102
            • 注册2008-04-20
            long aa;
            aa = (3985 * 25) / 4095 / 10;
            我改成上面的樣子,就不會出錯,不過答案還是0
            IAR為3.41版
            微控网感谢您的参与
            在线情况
            6
            • 头像
            • 级别
              • 积分51
              • 经验2657
              • 文章206
              • 注册2007-03-18
              呵呵,我刚试了一下,比你的现象更牛一点,IAR告诉我
              Warning[Pe550]: variable "aa" was set but never used D:\MyMCUPrg\TestMult\main.c 6
              明明用了,说我的变量从来没用过,哈哈。
              微控论坛特约嘉宾
              在线情况
              7
              • 头像
              • 级别
                • 积分8
                • 经验8471
                • 文章102
                • 注册2008-04-20
                我把long aa;放在main裡也會出現
                把它放在外面當全域變量,因該就不會出現那個問題,不過答案永遠都是0
                微控网感谢您的参与
                在线情况
                8
                • 头像
                • 级别
                  • 财富1
                  • 积分23
                  • 经验3096
                  • 文章276
                  • 注册2008-05-23
                  [QUOTE][B]下面引用由[U]leon1235[/U]发表的内容:[/B]

                  我的数学运算是为 (3985/4095)*2.5
                  答案算出来为0,好奇怪,我改成下面的样式还是不行,都是0
                  long aa;
                  aa= (long)3985/(long)4095*(long...[/QUOTE]


                  强制转换只能是低级的转换成高级的 你不能把一个float转换成long

                   把式子转化成aa=3985*25/4095/10也无济于事 因为计算机仍然式先做3985*25的  而3985*25>65535
                  实际上3985*2.5/4095 完全在int型的表示范围内(小数不计) 可以这样解决
                  unsigned int aa;

                  void main(void)
                  {
                  WDTCTL = WDTPW + WDTHOLD;
                  aa = (unsigned long)3985*25/4095;// 1 (结果是24)
                  aa = aa/10;//2 (结果是2)
                  }

                  这样的结果式aa=2  楼主应该是在12位AD冈量转换用到  其实你可以在第一句扩大个1000倍

                  aa = (unsigned long)3985*25*100/4095  然后把第2句aa = aa/10;//2 (结果是2)撤掉

                  这样得到的aa是你实际值的1000倍  只是在显示的时候 你在把小数点加上就OK 而且还保留了4位有效数字!
                  学习学习!~
                  在线情况
                  9
                  • 头像
                  • 级别
                    • 积分30
                    • 经验805
                    • 文章147
                    • 注册2008-07-09
                    ls说得很好,我经常这么处理~~~~
                    经有关部门鉴定为帅哥
                    在线情况
                    10
                    • 头像
                    • 级别
                      • 积分51
                      • 经验2657
                      • 文章206
                      • 注册2007-03-18
                      [QUOTE][B]下面引用由[U]bobo[/U]发表的内容:[/B]
                      强制转换只能是低级的转换成高级的 你不能把一个float转换成long

                       把式子转化成aa=3985*25/4095/10也无济于事 因为计算机仍然式先做3985*25的  而3985*25>65535
                      实际上3985*2.5/4095 完全在int型的表示范围内(小数不计) 可以这样解决...[/QUOTE]

                      那么,你所讲的意思是,如果要进行计算,需要控制一个式子内的计算结果不能超过int的最大限度了?但这个变量不是long型的吗?那样的式子,我在PC的C上没有问题。IAR中因为从来不用这么大的数,就没试过。今天一试还真有问题。
                      不过现在,我倒找到了解决办法,而且觉得比较可靠,其实很简单,就是把式子拆开,一步一步的算。
                      微控论坛特约嘉宾
                      在线情况
                      11
                      • 头像
                      • 级别
                        • 积分51
                        • 经验2657
                        • 文章206
                        • 注册2007-03-18
                        关于我说的拆式子的试验代码如下:
                        #include "io430.h"

                        void main( void )
                        {
                          unsigned long aa;
                          // Stop watchdog timer to prevent time out reset
                          WDTCTL = WDTPW + WDTHOLD;
                          aa = 4985;
                          aa *= 25;
                          aa /= 4095;
                          aa /= 10;
                        }

                            已经试过,此代码或获软件仿真通过,可以在Watch中看到aa的值最后等于3。当然3是去掉小数的结果,因为这个计算除不尽。看来,超界的不是变量,而是赋值号右边的算式,好像编译器只能对不超过int的数字常量进行计算,反而交给MSP430的部分是没有关系的了。
                            另外说明,在上述程序编译时,特别试过了io430,msp430x41x和msp430x44x的编译器,又分别选择和不选择编译器中的硬件乘法器选项,结果都是一样的,完全可以得到计算结果。
                            但我还是有疑问,就是为什么aa = 4985 * 25;是超界的,而aa = 65535 * 3; 却是正确的?后者的结果不比前者还大吗?但后者却通过了!谁对数学运算比较强,来解释一下?也许是我太相信C语言的通用性了,因为在PC机的TC或C++上这样的写法确实都是对的。
                        微控论坛特约嘉宾
                        在线情况
                        12
                        • 头像
                        • 级别
                        • 门派
                        • 职务总版主
                        • 声望+9
                        • 财富5
                        • 积分3065
                        • 经验390701
                        • 文章6744
                        • 注册2006-03-07
                        你试试产生三个变量为long,分别:A、B、C。
                        A=4985 B=25 然后C=A*B
                        你现在试试...NOW!
                        这很可能是编译为你的常数分配类型所导致的一些错误,而在用户定义为long类型后再做运算时。所以计算操作都以long类型来运算。
                        [COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
                        Powered by LeadBBS 9.2 .
                        Page created in 0.2500 seconds with 5 queries.