乘以两个数字

时间:2012-02-12 12:14:18

标签: c multiplication

几天前我接受了高通的采访。我是kinnda坚持一个问题,你看起来很简单的问题,但是如果有人能为这个问题提供任何好的解决方案,那么我和面试官都不满意我的答案。

问题是:

将2个数字相乘而不使用任何循环和加法,当然也没有乘法和除法。

我回复了:递归

他说其他任何事情都处于非常低的水平。

我想到的真正的想法是位移,但是位移只会将数字乘以2的幂,而对于其他数字,我们最终还要做一个补充。

例如:10 * 7可以完成:(二进制7 ~~ 111) 10 LT;&LT; 2 + 10 <&lt; 1 + 10 40 + 20 + 10 = 70

但又不允许添加。

对这个问题的任何想法的人。

8 个答案:

答案 0 :(得分:7)

这是一个只使用查找,添加和移位的解决方案。查找不需要乘法,因为它是指向另一个数组的指针数组 - 因此需要添加才能找到正确的数组。然后使用第二个值,您可以重复指针算术并获得查找结果。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  /* Note:As this is an array of pointers to an array of values, addition is
     only required for the lookup.

     i.e. 

     First part: lookup + a value -> A pointer to an array
     Second part - Add a value to the pointer to above pointer to get the value
  */
  unsigned char lookup[16][16] = {
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
    { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 },
    { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45 },
    { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 },
    { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75 },
    { 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90 },
    { 0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 105 },
    { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 },
    { 0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99, 108, 117, 126, 135 },
    { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150 },
    { 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 110, 121, 132, 143, 154, 165 },
    { 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, 168, 180 },
    { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195 },
    { 0, 14, 28, 42, 56, 70, 84, 98, 112, 126, 140, 154, 168, 182, 196, 210 },
    { 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225 }
  };
  unsigned short answer, mult;
  unsigned char x, y, a, b;

  x = (unsigned char)atoi(argv[1]);
  y = (unsigned char)atoi(argv[2]);
  printf("Multiple %d by %d\n", x, y);

  answer = 0;
  /* First nibble of x, First nibble of y */
  a = x & 0xf;
  b = y & 0xf;
  mult = lookup[a][b];
  answer += mult;
  printf("Looking up %d, %d get %d - Answer so far %d\n", a, b, mult, answer);

  /* First nibble of x, Second nibble of y */
  a = x & 0xf;
  b = (y & 0xf0) >> 4;
  mult = lookup[a][b];
  answer += mult << 4;
  printf("Looking up %d, %d get %d - Answer so far %d\n", a, b, mult, answer);

  /* Second nibble of x, First nibble of y */
  a = (x & 0xf0) >> 4;
  b = y & 0xf;
  mult = lookup[a][b];
  answer += mult << 4;
  printf("Looking up %d, %d get %d - Answer so far %d\n", a, b, mult, answer);

  /* Second nibble of x, Second nibble of y */
  a = (x & 0xf0) >> 4;
  b = (y & 0xf0) >> 4;
  mult = lookup[a][b];
  answer += mult << 8;
  printf("Looking up %d, %d get %d - Answer so far %d\n", a, b, mult, answer);

  return 0;
} 

答案 1 :(得分:3)

也许你可以递归添加,使用按位运算作为加法运算符的替代。请参阅:Adding Two Numbers With Bitwise and Shift Operators

答案 2 :(得分:2)

您可以先解决问题,首先实施添加,然后再根据添加进行乘法。

为了补充,使用C位运算符实现它们在门级处理器上的处理:

http://en.wikipedia.org/wiki/Full_adder

然后对于乘法,使用你实现的加法,使用goto语句和标签,这样就不会有循环语句(forwhiledo迭代语句)使用。

答案 3 :(得分:1)

俄罗斯农民增殖如何不使用添加?是否有一种简单的方法(几行,没有循环)来模拟仅使用AND,OR,XOR和NOT的加法?

答案 4 :(得分:1)

您可以按位运算符实现添加。但是,如果你想避免循环,你应该编写很多代码。 (我曾经在没有算术运算符的情况下实现乘法,但我使用循环,将索引移动到零。如果它可以帮助你,告诉我,我会搜索文件)

答案 5 :(得分:1)

您可以使用对数和减法。

log(a * b)= log(a)+ log(b)
a + b = - ( - a-b)
exp(log(a))= a

round(exp(-(-log(a)-log(b))))

答案 6 :(得分:0)

乘法表怎么样?

答案 7 :(得分:0)

问题:将2个数字相乘而不使用任何循环和加法,当然也没有乘法和除法。

乘法是根据加法定义的。在乘法实现中找不到加法是不可能的。

没有循环/递归,任意精度数都不能相乘。

两个固定比特长度的乘法可以通过表查找来实现。问题是表的大小。生成表需要添加。

答案是:无法完成。