【问题标题】:Multiplication of two integers using bitwise operators使用位运算符将两个整数相乘
【发布时间】:2011-05-26 06:44:22
【问题描述】:

如何使用位运算符将两个整数相乘?

我找到了一个实现here。有没有更好的方法来实现乘法?

例如:2 * 6 = 12 必须使用位运算符。

注意:数字是任意的,不是 2 的幂

【问题讨论】:

  • 必须取任意整数吗?如果其中一个操作数必须是 2 的幂,则有一种简单的方法可以实现乘法。此外,这是一项家庭作业,还是您尝试在具有不包含乘法(或两者)的指令集的处理器上实现汇编中的乘法?
  • 实现二的幂很容易,但在这种情况下,整数不是二的幂,它们是任意的。这不是作业问题,而是面试问题。请检查我附上的实现。
  • bitwise operator applications 上的维基百科条目有一些伪代码,但它使用加法运算符和位运算符。
  • 问题中的链接不存在

标签: bitwise-operators


【解决方案1】:
#include <stdio.h>

int main(void)
{
    int a, b, result;
    printf("Enter the numbers to be multiplied:");
    scanf("%d%d", &a, &b);       // a > b
    result = 0;
    while (b != 0)               // Iterate the loop till b == 0
    {
        if (b & 1)               // Bitwise & of the value of b with 1
        {
            result = result + a;  // Add a to result if b is odd .
        }
        a <<= 1;                    // Left shifting the value contained in 'a' by 1
                                  // Multiplies a by 2 for each loop
        b >>= 1;                    // Right shifting the value contained in 'b' by 1.
    }

    printf("Result: %d\n",result);
}

Source

【讨论】:

  • @Vector9 你有什么具体的事情需要了解吗?逻辑的核心是将一个值乘以 2,并在另一个值为奇数时将其加到结果中。它使用位移来乘(左)/除(右)2个输入。从算术运算符的角度考虑:while(b != 0): if(b is odd) {result = result + a;} a = a * 2; b = b/2;。一个简单的数学技巧。@Shiv 的技巧在他避开result = result + a 的地方更加巧妙
  • 是的,我明白你在做什么:a*b*(2/2)--> (a*2)*(b/2)。我没有得到的是为什么在奇数时使用 result = result + a。
  • 这个时间复杂度是多少?
  • 它的 O(b)(因为 a 乘以 b 倍)
  • @zengr 它是 O(log(b)),因为 b 每次迭代除以 2。
【解决方案2】:

组装算法: 这直接源于 ax*7 = (ax*8)-ax。

mov     bx, ax          ;Save AX*1
shl     ax, 1           ;AX := AX*2
shl     ax, 1           ;AX := AX*4
shl     ax, 1           ;AX := AX*8
sub     ax, bx          ;AX := AX*7

每个移位步骤都是乘以 2

【讨论】:

    【解决方案3】:

    在 C# 中 这是函数的实现。

        public static int Mul(int a, int b)
        {
            int r = 0;
            while (b != 0)
            {
                var temp = b & 1;
    
                if (temp!= 0)
                {
                    r = r + a;
                }
                a= a << 1;
                b= b >> 1;
                if (temp == 0)
                {
                    r = a;
                    break;
                }
            }
    
            return r;
        }
    

    【讨论】:

    • 此答案包含错误。我提交了一个编辑,要求版主删除错误,这是他的回复:更改答案代码的编辑几乎总是被拒绝。您需要在答案下方留下评论,或者您自己的新答案。 上面代码中的错误是if (temp == 0)。应删除包括 break 在内的整个 if 语句。要看到这一点,调用输入为 1 和 4 的函数:Mul(1, 4),返回值为 2。显然 1 x 4 不是 2。
    • 此代码指向错误。你为什么不检查发布的代码(接受的答案)?
    【解决方案4】:

    这个纯粹是按位运算。

    public int bitwiseMultiply(int a, int b) {
        if (a ==0  || b == 0) {
            return 0;
        }
    
        if (a == 1) {
            return b;
        }
        else
            if (b == 1) {
                return a;
            }
    
    
        int result = 0; // Not needed, just for test
        int initA = a;
        boolean isORNeeded = false;
        while (b != 0 ) {
    
            if (b == 1) {
                break;
            }
    
            if ((b & 1) == 1) { // Carry needed, odd number
                result += initA; // Test, not needed
                isORNeeded = true;
            }
    
            a <<= 1; // Double the a
            b >>= 1; // Half the b
            System.out.println("a=["+a+"], b=["+b+"], result=["+result+"]");
        }
    
        return (isORNeeded ? (a | initA) : a); // a + result;
    }
    

    【讨论】:

      【解决方案5】:
          #include<stdio.h>
          void main()
          {
              int n, m, i, j, x, large, small, t1, m2, result, a1, a2, a3, c, c1, c2, r, r1, la, re;
      
              printf("Enter two numbers\n");
              scanf("%d%d", &n, &m);
              result = 0;
      
              if (n > m)
              {
                  large = n;
                  small = m;
              }
              else
              {
                  large = m;
                  small = n;
              }
      
              c = 0;
      
              while (small)
              {
                  t1 = small;
                  t1 &= 1;
      
                  if (t1 == 1)
                  {
                      printf("\n %d", large);
                      la = large;
                      re = result;
                      m2 = 0;
                      r1 = 1;
                      while (re || la || c)
                      {
                          a2 = la;
                          a2 &= 1;
                          a3 = re;
                          a3 &= 1;
      
                          c1 = a2 & a3;
                          r = a3 ^ a2;
      
                          c2 =r & c;
                          r ^= c;
                          if (c1 || c2)
                              c = 1;
                          else
                              c = 0;
      
                          result &= ~r1;
                          x = r;
                          m2 >>= 1;
                          while (m2)
                          {
                              r <<= 1;
                              m2 >>= 1;
                          }
      
                          result |= r;
                          la >>= 1;
                          re >>= 1;
                          r1 <<= 1;
                          m2 = r1;
                      }
      
                  }
                  large <<= 1;
                  small >>= 1;
      
              }
              printf("\n%dX%d= %d\n", n, m, result);
          }
      

      【讨论】:

        【解决方案6】:

        我来这里是为了寻找这个问题,我发现 Zengr 的答案是正确的。谢谢曾格! 但是我想看看有一个修改是在他的代码中去掉“+”运算符。这应该使用 NO ARITHMETIC OPERATORS 将两个任意数字相乘,但都是按位。

        Zengr 的解决方案优先:

        #include<stdio.h>
        main()
        {
           int a,b,result;     
           printf("nEnter the numbers to be multiplied :");
           scanf("%d%d",&a,&b);         // a>b
           result=0;
           while(b != 0)               // Iterate the loop till b==0
           {
                if (b&01)                // Bitwise &  of the value of b with 01
                {
                  result=result+a;     // Add a to result if b is odd .
                }
                a<<=1;                   // Left shifting the value contained in 'a' by 1 
                                   // multiplies a by 2 for each loop
                b>>=1;                   // Right shifting the value contained in 'b' by 1.
           }
           printf("nResult:%d",result);
        }
        

        我的答案是:

        #include<stdio.h>
        main()
        {
           int a,b,result;     
           printf("nEnter the numbers to be multiplied :");
           scanf("%d%d",&a,&b);         // a>b
           result=0;
           while(b != 0)               // Iterate the loop till b==0
           {
                if (b&01)                // Bitwise &  of the value of b with 01
                {
                  result=add(result,a);     // Add a to result if b is odd .
                }
                a<<=1;                   // Left shifting the value contained in 'a' by 1 
                                        // multiplies a by 2 for each loop
                b>>=1;                   // Right shifting the value contained in 'b' by 1.
           }
           printf("nResult:%d",result);
        }
        

        我会将 add() 写为:

        int Add(int x, int y)
        {
            // Iterate till there is no carry  
            while (y != 0)
            {
                // carry now contains common set bits of x and y
                int carry = x & y;  
        
                // Sum of bits of x and y where at least one of the bits is not set
                x = x ^ y; 
        
                // Carry is shifted by one so that adding it to x gives the required sum
                y = carry << 1;
            }
            return x;
        }
        

        或递归添加为:

        int Add(int x, int y)
        {
            if (y == 0)
                return x;
            else
                return Add( x ^ y, (x & y) << 1);
        }
        

        添加代码来源:http://www.geeksforgeeks.org/add-two-numbers-without-using-arithmetic-operators/

        【讨论】:

          【解决方案7】:

          以下是使用位运算符将两个整数相乘的一种可能解决方案。

          #include <stdio.h>
          #define INT_BITS 32
          
          int multiply(int a, int b)
          {
              int pos1, pos2, res;
              for (pos1 = 0; pos1 < INT_BITS; pos1++)
                {
                  for (pos2 = 0; pos2 < INT_BITS; pos2++)
                    {
                      /* Find the bits set in both numbers and add their
                       * corresponding powers of 2. 
                       */
                      if ((a & (1 << pos1)) && (b & (1 << pos2)))
                        {
                          res = res + (1 << (pos1 + pos2));
                          // res = res + ((1 << pos1) << pos2);
                          /* Both the above statements calculating res are same */
                        }
                    }
                }
          
            return res;
          }
          
          
          int main()
          {
              int num1, num2, product;
              printf("Enter two numbers to be multiplied:");
              scanf("%d %d", &num1, &num2);
              product = multiply(num1, num2);
              printf("Product of %d and %d: %d\n", num1, num2, product);
              return 0;
          }
          

          函数 multiply() 可以使用 Shiv 的 Add() 函数进行如下微调:

          int Add(int x, int y)
          {
              if (y == 0)
                  return x;
              else
                  return Add( x ^ y, (x & y) << 1);
          }
          
          int multiply(int a, int b)
          {
              int pos1, pos2, res, temp;
              for (pos1 = 0; pos1 < INT_BITS; pos1++)
                {
                  for (pos2 = 0; pos2 < INT_BITS; pos2++)
                    {
                      /* Find the bits set in both numbers and add their
                       * corresponding powers of 2. 
                       */
                      if ((a & (1 << pos1)) && (b & (1 << pos2)))
                        {
                          temp = (1 << pos1) << pos2;
                          res = Add(res, temp);
                        }
                    }
                }
          
            return res;
          }
          

          【讨论】:

            猜你喜欢
            • 2016-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多