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

前端 未结 30 1491
别跟我提以往
别跟我提以往 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:19

    It's easy to avoid the '*' operator:

    mov eax, 1234h
    mov edx, 5678h
    imul edx
    

    No '*' in sight. Of course, if you wanted to get into the spirit of it, you could also use the trusty old shift and add algorithm:

    mult proc
    ; Multiplies eax by ebx and places result in edx:ecx
        xor ecx, ecx
        xor edx, edx
    mul1:
        test ebx, 1
        jz  mul2
        add ecx, eax
        adc edx, 0
    mul2:
        shr ebx, 1
        shl eax, 1
        test ebx, ebx
        jnz  mul1
    done:
        ret
    mult endp
    

    Of course, with modern processors, all (?) have multiplication instructions, but back when the PDP-11 was shiny and new, code like this saw real use.

    0 讨论(0)
  • 2020-12-01 02:20
    int multiply(int multiplicand, int factor)
    {
        if (factor == 0) return 0;
    
        int product = multiplicand;
        for (int ii = 1; ii < abs(factor); ++ii) {
            product += multiplicand;
        }
    
        return factor >= 0 ? product : -product;
    }
    

    You wanted multiplication without *, you got it, pal!

    0 讨论(0)
  • 2020-12-01 02:23

    This is the simplest C99/C11 solution for positive numbers:

    unsigned multiply(unsigned x, unsigned y) { return sizeof(char[x][y]); }
    
    0 讨论(0)
  • 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<unsigned>(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<int32_t>(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<uint16_t>(x) >> 1;
            y1 <<= 1;
        }
    
        if (prev_bit & ~sign_bit)
            result += y1;
    
        return result;
    }
    
    0 讨论(0)
  • 2020-12-01 02:26

    An integer left shift is multiplying by 2, provided it doesn't overflow. Just add or subtract as appropriate once you get close.

    0 讨论(0)
  • 2020-12-01 02:27
    unsigned int Multiply(unsigned int m1, unsigned int m2)
    {
        unsigned int numBits = sizeof(unsigned int) * 8; // Not part of the core algorithm
        unsigned int product = 0;
        unsigned int mask = 1;
        for(int i =0; i < numBits; ++i, mask = mask << 1)
        {
            if(m1 & mask)
            {
                product += (m2 << i);
            }
        }
        return product;
    }
    
    0 讨论(0)
提交回复
热议问题