获得2相关效果的优雅方式

时间:2015-01-02 23:30:12

标签: c

首先,抱歉模糊的标题。这是我的问题:

n > 0成为自然数。确定正数k,以使2^i + k = n为最大可能的i

我如何优雅地在C中做到这一点?

4 个答案:

答案 0 :(得分:2)

int i = 0; j = 1, k, n = (your value);

if ( n > 0 )
{
    while ( 2 * j < n) 
    {
        j = 2 * j; 
        i++;
    }

    k = n - j;
}

// replace '<' with '<=' if k = 0 is desired where n is a pure power of 2

(nb:标准C中没有取幂运算符)

答案 1 :(得分:2)

优雅在旁观者心中。

unsigned long find_remnant(unsigned long n) {
  for (unsigned long j, k = 0;
       (j = n&-n) != n;
       n -= j, k += j ) {
  }
  return k;
}

这是基于n&-n是n的二进制表示中的最低阶1位的事实。因此,循环从n中剥离一位,一次一个,将它们累积在k中,直到只留下一个1位,必须为2 ^ i。

由于循环在n中每个设置位执行一次,而不是在n中每位执行一次,因此可能更快。

如果它是一个问题,因为0&-0为0,如果使用0的参数调用(与问题规范相反),该函数将只返回0,这不是一个不合理的结果。

答案 2 :(得分:2)

unsigned long fn(unsigned long n) {
    int x;
    frexp(n, &x);
    return n - (1UL << (x-1)); }

请注意,对于n == 0(给出未定义的结果),这将失败,但您确实指定了n&gt; 0

答案 3 :(得分:1)

  1. 找出小于n的2的最大功率。 (通过向下舍入log2n)调用数字x。

  2. 您要查找的kn - 2^x.

  3. 你可以编写一个循环,检查每个小于n的两个幂。

    第一种方法更快。 (恒定时间对O(n)时间)