Division by constant using shifts and additions / subtractions

Hi all, I'm trying to split into an unsigned constant using only shifts and additions / subtractions. I have no problem with this if it were a multiplication, but I'm a bit puzzled by division.

For example, suppose that the constant divisor is 192 and allows you to say that the dividend is 8000

"full result" y = 8000/192 = 41 (assuming I don't store fractional bits)

y = 8000 → 8 ... 31 y = 8000 → 7 ... 62

But how do I get a more accurate solution?

Many thanks!

+3
source share
3 answers

There is almost certainly a more elegant way to do this, but here is enough to get you started.

, .

(: , (, n * 3 = (n*2) + (n*1) = (n << 1) + (n) ), ). " ", )

. ,

  • ( ints )

  • overflow ( 32- longs , uC, ,

  • (, 9/5 1 2? C 1, , , 2, ?)

  • , ( ), ( ). , .

, , , .

192 , 1/192, (64 * 3). () 1/3, 0x5555/(1 < 16).

192, 64, 3. 3, 0x5555 16 ( 0x55 → 8 ...)

//                8000/192          =
//                ((8000/64)/3)     =
//                ((8000 >> 6) / 3) =
//                (((8000 >> 6) * 0x5555) >> 16)
//                (((8000 * 0x5555) >> 22

, . (8000 * (0x5555/(1 << 16)), 0, 0. .

, 1- :

 printf("Answer:  %lu\n", ((8000UL * 0x5555UL) >> 22));

41, "C" 8000/192, 42 "". LSB, , .

, , , - .

+9

, . " ".

"kdiv" sourceforge:

http://sourceforge.net/projects/kdiv/

+4

. , , 192, 0xC0, 0x40, shift 8000 → 6 = 125. 8000/192 → 125/3, 3. , - 125/2 125/4. 125 0x7d b1111101, 3 b100000 + 11101, (3 0x20) + (3 8) + 5, 125/3 = 0x20 + 0x8 + (5/3) 5/3 1, 2, 0x28 + 1 = 41. , . , , .

+2
source

Source: https://habr.com/ru/post/1789743/


All Articles