Hello experts, to avoid a division, I use integer arithmetics. The unsigned int x which is in the range of 2000 is first multiplied by a number s which is 2048 plus/minus 1000 and then shifted by 11 digits which should replace a division by 2048.
unsigned int near x; unsigned int s x = ( (unsigned long) x * (unsigned long) s ) >> 11 ;
x = (unsigned int) (x * s) / 2048UL; Unfortunately the above won't work as the cast to unsigned int has higher precedence than the division. You need to use: x=(unsigned int)((x*s)/2048UL); I feel it is always better to use parentheses to make your intentions clearer even when not required.
Hello, I tried this on my system and the results were fine. The assembly code is;
s is assigned to R5 x is assigned to R4 MOV R5, DPP2:s MOV R4, DPP2:x MULU R4, R5 ;x*s MOV R5, MDH MOV R4, MDL MOV R6, R5 SHR R4, #0x0B ;>>11 (32-bit) SHL R6, #0x05 OR R4, R6 MOV DPP2:x, R4
Oh, one other thing. If you must bit-shift, C only guarantees that you will pull in zeros when left shifting. Right shifting is implementation defined. So, in your example, you should AND off the top 11 bits of the result before using it.
First, I am pretty sure any compiler written today will convert var / 2048 to a proper right shift of 11 bits so let the compiler do the work for you. Second, only one term in an expression need be a larger type to convert the entire expression to that type. E.g.
x = (unsigned int) (x * s) / 2048UL;
View all questions in Keil forum