在线情况
1
  • 头像
  • 级别
    • 积分51
    • 经验2657
    • 文章206
    • 注册2007-03-18
    你这个问题我没有试过,因为我总是尽量避免出现这样的运算,大多数情况下,我会变成这样的方法来写:
    long aa;
    aa = 4985 * 25 / 4095 / 10;
    我写这种式子的原则就是,式中参数不带小数,先乘后除,注意防止溢出。
    微控论坛特约嘉宾
    在线情况
    2
    • 头像
    • 级别
      • 积分51
      • 经验2657
      • 文章206
      • 注册2007-03-18
      哦?莫非不支持long型变量了?
      微控论坛特约嘉宾
      在线情况
      3
      • 头像
      • 级别
        • 积分51
        • 经验2657
        • 文章206
        • 注册2007-03-18
        呵呵,我刚试了一下,比你的现象更牛一点,IAR告诉我
        Warning[Pe550]: variable "aa" was set but never used D:\MyMCUPrg\TestMult\main.c 6
        明明用了,说我的变量从来没用过,哈哈。
        微控论坛特约嘉宾
        在线情况
        4
        • 头像
        • 级别
          • 积分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中因为从来不用这么大的数,就没试过。今天一试还真有问题。
          不过现在,我倒找到了解决办法,而且觉得比较可靠,其实很简单,就是把式子拆开,一步一步的算。
          微控论坛特约嘉宾
          在线情况
          5
          • 头像
          • 级别
            • 积分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++上这样的写法确实都是对的。
            微控论坛特约嘉宾
            在线情况
            6
            • 头像
            • 级别
              • 积分51
              • 经验2657
              • 文章206
              • 注册2007-03-18
              经过试验,将版主的思路整理了一下,应该明白为什么了,我将思路再说清一点,就以我最后那两个计算的对比,大家就可以理解了。
              aa = 4985 * 25;得到的结果是超界的,这是因为4985只需要2个字节空间,所以编译器默认为4985分配了两个字节也就是最小能存放开的空间用来存这个常量,接下来做乘法操作,所乘的结果却超出了存放这个常量的空间,结果就产生了溢出!注意这个空间与aa变量本身是无关的,aa是要等到4985 * 25的这个计算出来结果之后才被赋值的,而如果这时在4985上加强制类型转换,要求以long分配常量空间,就可以得到正确结果,即 aa = (long) 4985 * 25; 。后一个不需要转换,因为结果是向前边的空间存的,我想这个方向应该是跟运算符的结合性有关,所以如果是别的运算还要注意,不一定是前边的要强制类型。
              aa = 65535 * 3;得到的结果并不超界,是因为65535虽然没有超过65536,但系统默认分配两个字节时是int,而不是unsigned int,这与编译器的设置可能有关,我记得有一个选择默认是有还是无符号的选项,所以因此造成大于32767的值都会当作long处理,所以空间已经有4个字节了,当然就可以任意计算了,别说乘3,乘32767都可以。实际上,最大可以写的是65536*32767,再大就必须声明为无符号了。

              实验最终完毕,对此问题我已不会再心存疑问了。
              微控论坛特约嘉宾
              在线情况
              7
              • 头像
              • 级别
                • 积分51
                • 经验2657
                • 文章206
                • 注册2007-03-18
                [QUOTE][B]下面引用由[U]bobo[/U]发表的内容:[/B]
                ... 你说65535*32767是最大的?可是我发现65535*32768也可以!...[/QUOTE]

                请细看一下,我写的是65536*32767。若是65535的话*32768当然也可以,只要不超过signed int就行了。

                关于IAR设置我看了,确实只能设置char的默认,int的大概就是默认只有signed,所以希望大家最好能在定义变量时不要省略掉unsigned这个标志。
                微控论坛特约嘉宾
                Powered by LeadBBS 9.2 .
                Page created in 0.0781 seconds with 7 queries.