How can I perform multiplication without the '*' operator?

前端 未结 30 1504
别跟我提以往
别跟我提以往 2020-12-01 01:47

I was just going through some basic stuff as I am learning C. I came upon a question to multiply a number by 7 without using the * operator. Basically it\'s like this

<
30条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-01 02:25

    Shift and add doesn't work (even with sign extension) when the multiplicand is negative. Signed multiplication has to be done using Booth encoding:

    Starting from the LSB, a change from 0 to 1 is -1; a change from 1 to 0 is 1, otherwise 0. There is also an implicit extra bit 0 below the LSB.

    For example, the number 5 (0101) will be encoded as: (1)(-1)(1)(-1). You can verify this is correct:

    5 = 2^3 - 2^2 + 2 -1

    This algorithm also works with negative numbers in 2's complement form:

    -1 in 4-bit 2's complement is 1111. Using the Booth algorithm: (1)(0)(0)(0)(-1), where there is no space for the leftmost bit 1 so we get: (0)(0)(0)(-1) which is -1.

    /* Multiply two signed integers using the Booth algorithm */
    int booth(int x, int y)
    {
        int prev_bit = 0;
        int result = 0;
    
        while (x != 0) {
            int current_bit = x & 0x1;
            if (prev_bit & ~current_bit) {
                result += y;
            } else if (~prev_bit & current_bit) {
                result -= y;
            }
    
            prev_bit = current_bit;
    
            x = static_cast(x) >> 1;
            y <<= 1;
        }
    
        if (prev_bit)
            result += y;
    
        return result;
    }
    

    The above code does not check for overflow. Below is a slightly modified version that multiplies two 16 bit numbers and returns a 32 bit number so it never overflows:

    /* Multiply two 16-bit signed integers using the Booth algorithm */
    /* Returns a 32-bit signed integer */
    int32_t booth(int16_t x, int16_t y)
    {
        int16_t prev_bit = 0;
        int16_t sign_bit = (x >> 16) & 0x1;
        int32_t result = 0;
        int32_t y1 = static_cast(y);
    
        while (x != 0) {
            int16_t current_bit = x & 0x1;
            if (prev_bit & ~current_bit) {
                result += y1;
            } else if (~prev_bit & current_bit) {
                result -= y1;
            }
    
            prev_bit = current_bit;
    
            x = static_cast(x) >> 1;
            y1 <<= 1;
        }
    
        if (prev_bit & ~sign_bit)
            result += y1;
    
        return result;
    }
    

提交回复
热议问题