我们以int
为例:
int SetBitWithinRange(const unsigned from, const unsigned to)
{
//To be implemented
}
SetBitWithinRange
应该返回int
,其中所有且仅从位from
到位to
的位被设置,当来自{{1}时比smaller
而且两者都在to
到0
的范围内。
例如为:
32
会导致int i = SetBitWithinRange(2,4)
的值为0b00 ... 01100
答案 0 :(得分:5)
以下是一些方法。首先,“set n
位的一些变体,然后由from
”移位。我会用C#回答,我比它更熟悉它。应该很容易转换。
uint nbits = 0xFFFFFFFFu >> -(to - from);
return nbits << from;
下行:无法处理空范围,即to <= from
。
uint nbits = ~(0xFFFFFFFFu << (to - from));
return nbits << from;
上行:可以处理to = from
的情况,在这种情况下,它不会设置位
下行:无法处理全部范围,即设置所有位。
显然这些是如何工作的。
或者,您可以使用“减去两个2的幂”技巧,
(1u << to) - (1u << from)
下行:to
不能为32,所以你永远不能设置最高位。
像这样工作:
01000000
^^^^^^ "to" zeroes
100
^^ "from zeroes"
-------- -
00111100
在“from”部分的1的右侧,它只是从零中减去零。然后在“from”部分的1处,您将从1减去(如果to == from
)并得到0作为结果,或者您将从0减去1并一直借用到to
部分中的1,将被重置。
在撰写本文时提出的所有真正的按位方法都有其中一个缺点,这就提出了一个问题:它可以毫无缺点地完成吗?
不幸的是,答案令人失望。它可以在没有缺点的情况下完成,但仅限于
举一个例子,您可以选择以前的任何方法,并添加一个特殊情况(使用if
或三元运算符)来解决它们的缺点。
举例2 :(未经测试)
uint uppermask = (((uint)to >> 5) ^ 1) << to;
return uppermask - (1u << from);
uppermask
取1并将其向左移动to
(照例),或者取0并向左移动(量数无关紧要,因为它为0正在转移),如果to == 32
。但它有点奇怪并且使用更多操作。
举一个3的例子,当你按操作数大小移动时给出零的移位可以很容易地解决这个问题。不幸的是,这种转变并不常见。
答案 1 :(得分:3)
我会选择类似的东西:
int answer = 0;
unsigned i = from;
for (; i <= to; ++i)
answer |= (1 << i);
return answer;
易于实施&amp;可读的。
我认为最快的方法是预先计算所有可能的值(从(0,0)到(32,32),如果你知道你只将它用于32位整数) 。事实上,其中大约有1000个。
然后你最终会得到O(1)解决方案:
answer = precalcTable[from][to];
答案 2 :(得分:3)
怎么样:
return (to<32 ? (1<<to) : 0) - (1<<from);
当然,这并未完全检查from
和to
的有效性。
根据@JosephQuinsey的评论编辑。
答案 3 :(得分:2)
有效地实现这一目标的常见方法是:
uint32_t set_bits_32 (uint32_t data, uint8_t offset, uint8_t n)
{
uint32_t mask = 0xFFFFFFFF >> (32-n);
return data | (mask << offset);
}
答案 4 :(得分:1)
也许:(( 1 << to ) - (1 << from)) | (1 << to)
这也将根据请求设置to和from
答案 5 :(得分:1)
这是我的答案。 (更新)
unsigned int SetBits(int from, int to)
{
return (UINT_MAX >> (CHAR_BIT*sizeof(int)-to)) & (UINT_MAX << (from-1));
}
SetBits(9,16); ==> 0b 1111 1111 0000 0000
SetBits(1,1); ==> 0b 0000 0001 // Just Bit #1
SetBits(5,5); ==> 0b 0001 0000 // Just Bit #5
SetBits(1,4); ==> 0b 0000 1111 // Bits #1, #2, #3, and #4 (low 4 bits)
SetBits(1,32); ==> 0b 1111 1111 1111 1111 // All Bits
但是,SetBits(0,0);
无法关闭所有位。
我的假设:
from
或to
进行检查;调用者必须传递正确的值。答案 6 :(得分:0)
也可以这种方式完成,可以使用移位操作实现pow。
{
unsigned int i =0;
i = pow(2, (to-from))-1;
i = i <<from;
return i;
}