如何仅使用C中的位操作返回整数左侧的连续数(不是if,for,while等)? 我不知道从哪里开始解决这个问题。
//BurstSize(-1) = 32,
//BurstSize(0xFFF0F0F0) = 12
//Legal: ! ~ & ^ | + << >>
//Max ops: 50
int BurstSize(int a) {
//code
}
答案 0 :(得分:2)
如果您使用GCC,则可以调用__builtin_clz()
来计算前导零。反转输入,然后它可用于计算前导数。
int BurstSize(unsigned a) {
return __builtin_clz(~a);
}
如果您无法访问__builtin_*()
,那么您可以实现Hacker's Delight中的前导零点计数功能:
int nlz4(unsigned x) {
int y, m, n;
y = -(x >> 16); // If left half of x is 0,
m = (y >> 16) & 16; // set n = 16. If left half
n = 16 - m; // is nonzero, set n = 0 and
x = x >> m; // shift x right 16.
// Now x is of the form 0000xxxx.
y = x - 0x100; // If positions 8-15 are 0,
m = (y >> 16) & 8; // add 8 to n and shift x left 8.
n = n + m;
x = x << m;
y = x - 0x1000; // If positions 12-15 are 0,
m = (y >> 16) & 4; // add 4 to n and shift x left 4.
n = n + m;
x = x << m;
y = x - 0x4000; // If positions 14-15 are 0,
m = (y >> 16) & 2; // add 2 to n and shift x left 2.
n = n + m;
x = x << m;
y = x >> 14; // Set y = 0, 1, 2, or 3.
m = y & ~(y >> 1); // Set m = 0, 1, 2, or 2 resp.
return n + 2 - m;
}
int BurstSize(unsigned a) {
return nlz4(~a);
}
答案 1 :(得分:1)
最简单的方法:反转数字,然后找到最重要的位集。其余的你可以自己做(我99%肯定这是一个功课问题,所以我只给出一个提示。如果你真的需要更多帮助,请在评论中提问,我会进一步扩展。)
至于找到最重要的位集,请查看https://stackoverflow.com/a/21413883/1967396
是一种相当有效的方法。
更新现在找到一个完整的方法,找到最重要的位集(反转后),然后使用一个聪明的查找表转换为实际的字节(模块37技巧没有来自我...我在http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup找到它,但做了一个小改动,所以它适用于32位设置)。我包含了测试0到32位模式的代码 - 似乎可行。
#include <stdio.h>
int burstSize(int n) {
// return number of consecutive bits set
unsigned int m, r;
m = ~n;
m = m | m >> 1;
m = m | m >> 2;
m = m | m >> 4;
m = m | m >> 8;
m = m | m >> 16;
m = ((m ^ (m >> 1)) | 0x80000000) & m;
static const int Mod37BitPosition[] = // map a bit value mod 37 to its position
{
-1, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4,
7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5,
20, 8, 19, 18
};
r = Mod37BitPosition[m % 37]; // <<<< not sure if this is allowed in your assignment...
return 31 - r; // <<< you could rewrite the LUT so you don't need an operation here. I was lazy.
}
int main(void) {
printf("%d\n", burstSize(0x00000000));
printf("%d\n", burstSize(0x80000000));
printf("%d\n", burstSize(0xC0000000));
printf("%d\n", burstSize(0xE0000000));
printf("%d\n", burstSize(0xF0000000));
printf("%d\n", burstSize(0xF8000000));
printf("%d\n", burstSize(0xFC000000));
printf("%d\n", burstSize(0xFE000000));
printf("%d\n", burstSize(0xFF000000));
printf("%d\n", burstSize(0xFF800000));
printf("%d\n", burstSize(0xFFC00000));
printf("%d\n", burstSize(0xFFE00000));
printf("%d\n", burstSize(0xFFF00000));
printf("%d\n", burstSize(0xFFF80000));
printf("%d\n", burstSize(0xFFFC0000));
printf("%d\n", burstSize(0xFFFE0000));
printf("%d\n", burstSize(0xFFFF0000));
printf("%d\n", burstSize(0xFFFFF800));
printf("%d\n", burstSize(0xFFFFFC00));
printf("%d\n", burstSize(0xFFFFFE00));
printf("%d\n", burstSize(0xFFFFFF00));
printf("%d\n", burstSize(0xFFFFFFF8));
printf("%d\n", burstSize(0xFFFFFFFC));
printf("%d\n", burstSize(0xFFFFFFFE));
printf("%d\n", burstSize(0xFFFFFFFF));
}
答案 2 :(得分:0)
尝试这个:
unsigned int A=0XFFF0; //your own number
unsigned int B0=(1 & A)/1;
unsigned int B1=(2 & A)/2;
unsigned int B2=(4 & A)/4;
unsigned int B3=(8 & A)/8;
unsigned int B4=(16 & A)/16;
unsigned int B5=(32 & A)/32;
unsigned int B6=(64 & A)/64;
unsigned int B7=(128 & A)/128;
unsigned int B8=(256 & A)/256;
unsigned int B9=(512 & A)/512;
unsigned int B10=(1024 & A)/1024;
unsigned int B11=(2048 & A)/2048;
unsigned int B12=(4096 & A)/4096;
unsigned int B13=(8192 & A)/8192;
unsigned int B14=(16384 & A)/16384;
unsigned int B15=(32768 & A)/32768;
int Result=B15+
B14*(B15)+
B13*(B14*B15)+
B12*(B13*B14*B15)+
B11*(B12*B13*B14*B15)+
B10*(B11*B12*B13*B14*B15)+
B9*(B10*B11*B12*B13*B14*B15)+
B8*(B9*B10*B11*B12*B13*B14*B15)+
B7*(B8*B9*B10*B11*B12*B13*B14*B15)+
B6*(B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B5*(B6*B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B4*(B5*B6*B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B3*(B4*B5*B6*B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B2*(B3*B4*B5*B6*B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B1*(B2*B3*B4*B5*B6*B7*B8*B9*B10*B11*B12*B13*B14*B15)+
B0*(B1*B2*B3*B4*B5*B6*B7*B8*B9*B10*B11*B12*B13*B14*B15);
答案 3 :(得分:0)
以下答案会反转执行操作的数字,它不会使用%
运算符,但会使用一个-
符号:
#include <iostream>
int burstSize(int n) {
// Reverse the bits
n = (n & 0x55555555) << 1 | (n & 0xAAAAAAAA) >> 1;
n = (n & 0x33333333) << 2 | (n & 0xCCCCCCCC) >> 2;
n = (n & 0x0F0F0F0F) << 4 | (n & 0xF0F0F0F0) >> 4;
n = (n & 0x00FF00FF) << 8 | (n & 0xFF00FF00) >> 8;
n = (n & 0x0000FFFF) << 16 | (n & 0xFFFF0000) >> 16;
// rightmost 0-bit, produces 0 if none (e.g., 10100111 -> 00001000)
int r = ~n & (n + 1);
// r - 1 will give us a mask of the consequtive 1s to isolate (e.g., 0100 -> 0011)
n = (r - 1) & n;
// Count the bits
n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
n = (n & 0x0F0F0F0F) + ((n >> 4) & 0x0F0F0F0F);
n = (n & 0x00FF00FF) + ((n >> 8) & 0x00FF00FF);
n = (n & 0x0000FFFF) + ((n >>16) & 0x0000FFFF);
// Return the bit count
return n;
}
int main() {
std::cout << burstSize(0x00000000) << std::endl; // 0
std::cout << burstSize(0x00010F00) << std::endl; // 0
std::cout << burstSize(0x80010F00) << std::endl; // 1
std::cout << burstSize(0xF0010F00) << std::endl; // 4
std::cout << burstSize(0xFFFFFFFE) << std::endl; // 31
std::cout << burstSize(0xFFFFFFFF) << std::endl; // 32
return 0;
}