我正在尝试使用C中的位操作来执行此操作。
From a number n, substract the largest power of 2 smaller than n.
For example:
6 - 4 = 2
11 - 8 = 3
我的方法是:
next2power = nextHighestPowerOf2(n)
previous2power = next2power >> 1;
result = n - previous2power;
我在nextHighestPowerOf2()
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
中使用了来自Bit Twiddling Hacks的黑客攻击。
next2power
即使我使用unsigned long long
,问题仍然是n
溢出。 2^64
的顺序为1
。所以这种方法对我不起作用。
这两种替代方法可以在这里工作:
0
翻转为n
。n
的最高功率而不会溢出,然后从 {
folder: true,
name: 'D:',
children: [
{name: 'Game of Thrones s05e01.avi', size: '1034 mb', type: 'Movie', dateModified: '13/03/2014 10:14'},
{name: 'The Knick s01e01', size: '523 mb', type: 'Text Document', dateModified: '27/11/2012 04:12'},
{name: 'musicbackup1.zip', size: '25 mb', type: 'Compressed Zip File', dateModified: '18/03/2014 00:56'},
{name: 'musicbackup2.zip', size: '25 mb', type: 'Compressed Zip File', dateModified: '18/03/2014 00:56'}
]
}
但我想不出任何解决方案。有没有人知道其他方法来实现这个目标?
答案 0 :(得分:3)
这应该可以解决您的问题
unsigned long long int res = n - 1ULL<<( (int)log2(n-1) );
当然,当n <= 1
时,你必须设置特殊条件答案 1 :(得分:2)
如果你有64位int。您需要添加v | = v&gt;&gt; 32复制到低32位。
答案 2 :(得分:2)
虽然n
不是2的幂,但请保持关闭设置的最小值。您可以使用n &= (n-1);
进行后一种操作(考虑一下)。
在C99中表达:
#include <stdio.h>
int f(int n) {
while (n & (n-1)) { // n is *not* a power of two
n &= (n-1);
}
return n;
}
int main() {
for (int n = 1; n < 130; ++n) {
printf("%d : %d\n", n, f(n));
}
}
这样做的好处是运行时间与设置的位数成正比。
示例输出:
blazs@blazs:/tmp$ ./x
1 : 1
2 : 2
3 : 2
4 : 4
5 : 4
6 : 4
7 : 4
8 : 8
9 : 8
10 : 8
11 : 8
12 : 8
13 : 8
14 : 8
15 : 8
16 : 16
17 : 16
18 : 16
19 : 16
20 : 16
答案 3 :(得分:0)
取最高设置位几乎总是有效,这很容易:
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32; // you need this line for 64bit numbers
v &= ~(v >> 1);
但并非总是如此。如果n
已经是2的幂,则其最高设置位等于其自身,不小于。所以把v--
放在后面。
FWIW,只要你有一个正确的内置方法来获取整数日志(bsr
或等价物),记录和移位可能会更快。 FP日志可能是一场灾难。
ps:这些都没有经过测试。
答案 4 :(得分:0)
我认为你在进入或打印你的价值观时可能会犯错误;你问题中的代码对我有用:
#include <stdio.h>
int main() {
unsigned long long input, v;
input = 7597026128958891522ULL;
v = input;
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
v= v>>1;
printf("Input %llu, next lower power of 2 %llu\n", input, v);
}
产生
Input 7597026128958891522, next lower power of 2 4611686018427387904