2个数字中的共同因素是什么?

时间:2014-04-04 10:13:40

标签: c++ algorithm

一般情况下,我们发现两个数字之间的共同因素,即8和12为4。 但是在编程语言中,当两个数字除以2时,我想找到公共数字。 我们将两个数字除以2并检查公共数字 喜欢数字8和11 8-将4-→2 11-将5-→2 她的公共号码是2。 我想有效地实现它高达10 ^ 9的数字。 她是我的实施

long long i,j;
while(i!=1||j!=1)
{
    i=i/2;
    j=j/2;
    if(i==j)
    flag=1;
    break;
}

但是我和j在不同的时间会相同。如何实现呢?

2 个答案:

答案 0 :(得分:4)

你可以用更复杂的逻辑来做到这一点 - 使用两个数字并且总是将它们中的较大数字分开:

int get(int a, int b) {
  while (a != b) {
    if (a < b) {
      swap(a, b);
    }
    a /= 2;
  }
  return a;
}

说明:当除以2时,任何正整数最终会变为1,因此周期将终止,当ab都为1时,这将发生在最坏的情况。每一步我确保a不小于b然后我除以2.

答案 1 :(得分:2)

  

我希望在两个数字除以2时找到公共数字

你的问题有点模糊。我假设你想要找到2的最大公共分割能力?

由于它们的尾随零,可以很容易地以二进制检测到2的幂:

  1    00000001
  2    00000010
  4    00000100
  8    00001000
 16    00010000
 32    00100000
 64    01000000
128    10000000

所有在其素数因子分解中具有单个2的数字只有一个尾随零:

  2    00000010    2
  6    00000110    2*3
 10    00001010    2*5
 14    00001110    2*7
 18    00010010    2*3*3

您可以对4,8,16等的倍数执行相同的操作,并且可以得出结论:您可以通过其二进制表示中的尾随零的数量来检测数字中2的幂。

2的倍数(不是4的倍数)将以10结尾,4的倍数(不是8的倍数)将以100结尾,依此类推。在最右边的1之前的位对我们来说并不感兴趣。

所以我们想做的就是隔离最右边的1位。幸运的是,有一个很好的技巧:

int rightmost_bit(int x)
{
    return x & -x;
}

这是如何工作的?如果你看两个补码中的x-x的二进制表示,它们只共享一个1位,即最右边的,这正是我们感兴趣的那个:

           *
 40    00101000
-40    11011000
&          *
  8    00001000

x最右边的位右侧的所有位在-x中也为0,而-x左侧的所有位都与x中的位相反因此,当它们与binary-and。

组合时,它们会相互抵消

找到最大公共分割能力2的天真方法是:

int gcd_p2_naive(int a, int b)
{
    return std::min(rightmost_bit(a), rightmost_bit(b));
}

但是我们可以用另一个简单的技巧做得更好,我刚想出来的那个:

int gcd_p2(int a, int b)
{
    return rightmost_bit(a | b);
}

为什么这样做?我会将这种开放作为读者的练习;)