首先,抱歉模糊的标题。这是我的问题:
让n > 0
成为自然数。确定正数k
,以使2^i + k = n
为最大可能的i
。
我如何优雅地在C中做到这一点?
答案 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)
找出小于n的2的最大功率。 (通过向下舍入log2n)调用数字x。
您要查找的k
是n - 2^x.
或强>
你可以编写一个循环,检查每个小于n的两个幂。
第一种方法更快。 (恒定时间对O(n)时间)