unexpected results in integer arithmetics

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 ;

For testing I used s=2048. The result should be (x*2048)>>11 = x, but what I get as a result is about 30 times too big, and all results for different values of x are multiples of 0x20.

Type casting problem?

Please help, I run out of ideas.

Parents
  • 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;
    should give you the correct result (32 bits should always be able to contain 16 x 16 bits multiplies) with a compiler-warning-silencing final cast back to the smaller type of unsigned int. Try the above and see what assembler you get. See what result you get.

    HTH.

Reply
  • 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;
    should give you the correct result (32 bits should always be able to contain 16 x 16 bits multiplies) with a compiler-warning-silencing final cast back to the smaller type of unsigned int. Try the above and see what assembler you get. See what result you get.

    HTH.

Children
More questions in this forum