俄罗斯农民增殖

时间:2008-11-04 01:11:24

标签: c algorithm optimization multiplication

这是我Russian Peasant Multiplication的简短实现。如何改进?

限制:仅在> 0,b> 0

时有效
for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

10 个答案:

答案 0 :(得分:55)

可以通过添加空格,适当的缩进和适当的函数体来改进它:

int peasant_mult (int a, int b) {
  for (p = 0;
       p += (a & 1) * b, a != 1;
       a /= 2, b *= 2);
  return p;}

请参阅?现在很清楚如何使用for声明的三个部分。请记住,程序主要是为人眼编写的。不可读的代码总是错误的代码。

现在,为了我个人的娱乐,一个尾递归版本:

(defun peasant-mult (a b &optional (sum 0))
  "returns the product of a and b,
   achieved by peasant multiplication."
  (if (= a 1)
      (+ b sum)
      (peasant-mult (floor (/ a 2))
                    (* b 2)
                    (+ sum (* b (logand a 1))))))

答案 1 :(得分:20)

我认为这太可怕了 这与编译器的观点完全相同,并且(希望)更清晰

int sum = 0;
while(1)
{
    sum += (a & 1) * b;
    if(a == 1)
       break;

    a = a / 2;
    b = b * 2;
}

现在我把它写出来了,我明白了。

答案 2 :(得分:14)

有一种非常简单的方法可以改善这种情况:

p = a * b;

它甚至具有a或b可能小于0的优点。

如果看看它是如何工作的,你会发现它只是正常的手动乘法执行二进制。你的计算机是通过这种方式实现的(1),因此使用俄罗斯农民方法的最简单方法是使用内置乘法。

(1)也许它有一个更复杂的算法,但原则上你可以说,它适用于这个算法

答案 3 :(得分:7)

循环中仍然存在乘法。如果您想降低乘法的成本,可以改为使用它:

for(p=0;p+=(-(a&1))&b,a!=1;a>>=1,b<<=1);

答案 4 :(得分:5)

我发现它并不像其他人所说的那样特别可怕,模糊不清或不可读,而且我不理解所有那些事。这就是说,这就是我如何“改进”它:

// Russian Peasant Multiplication ( p <- a*b, only works when a>0, b>0 )
// See http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
for( p=0; p+=(a&1)*b, a!=1; a>>=1,b<<=1 );

答案 5 :(得分:4)

p未初始化。

如果a为零会怎样?

如果a为负数会怎样?

更新:我发现您已更新问题以解决上述问题。虽然您的代码现在似乎按照规定工作(溢出问题除外),但它的可读性仍然低于应有的程度。

答案 6 :(得分:4)

这是代码混淆比赛吗?我想你可以做得更好。对于初学者来说,使用误导性的变量名而不是无意义的变量名。

答案 7 :(得分:3)

我认为它不完整,而且很难阅读。你在寻找什么具体的反馈意见?

答案 8 :(得分:2)

int RussianPeasant(int a, int b)
{
    // sum = a * b
    int sum = 0;
    while (a != 0)
    {
        if ((a & 1) != 0)
            sum += b;
        b <<= 1;
        a >>= 1;
    }
    return sum;
}

答案 9 :(得分:0)

没有乘法或除法的答案:

function RPM(int a, int b){
    int rtn;
    for(rtn=0;rtn+=(a&1)*b,a!=1;a>>=1,b<<=1);
    return rtn;
}