C:最有效的方法来设置一个变量内的范围内的所有位 [英] C: Most efficient way to set all bits in a range within a variable
问题描述
让我们来 INT
为例:
INT SetBitWithinRange(从常量,符号常量符号来)
{
//要实现
}
SetBitWithinRange
应该返回一个 INT
中的所有,只起始于位位从
来位到
设置,当从为小
比到
无一不是在 0
向范围 32
。
例如为: INT I = SetBitWithinRange(2,4)
将导致 I
具有0b00的... 01100 <值/ p>
这里有一些方法。首先,一些变种设置 N
位,然后通过从
转变。我会在C#中回答虽然,我更熟悉它比我与C.应该很容易转换。
UINT NBITS = 0xFFFFFFFFu&GT;&GT; - (至 - 从);
返回NBITS&LT;&LT;从;
缺点:不能处理一个空的范围,即其中到&lt的情况下,从=
UINT NBITS =〜(0xFFFFFFFFu&LT;&LT;(来 - 从));
返回NBITS&LT;&LT;从;
上行:可以处理的情况下,其中从
=在这种情况下将设置没有位结果
缺点:不能处理的全范围,例如设定所有位
这应该是显而易见如何工作的。
另外,你可以用减两两权招,
(1U&LT;&LT;至) - (1U&LT;&LT;从)
缺点:到
不能32,所以你永远无法设定最高位
是这样的:
01000000
^^^^^^至零
100
^^从零
-------- -
00111100
要1中的从的一部分,它只是零正在从零减去的权利。然后在从部分1,你要么从1减去(如从==
),并得到0作为一个结果,否则你会减1从0和借一路1在到
部分,它会被清除。
这已经提出在写作的时候所有真正的逐位的方法有那些缺点之一,这提出了一个问题:能不能没有缺点做
答案是,很不幸,令人失望。它可以在不负面影响,而仅由
进行- 欺骗(即使用非按位元素),或
- 的操作量超出就好了,或者
- 不规范操作
要举1个例子,你可以随便挑任何previous方法和添加特殊情况下(与如果
或三元运营商)工作在他们的缺点。
要举2个例子:(未测试)
UINT uppermask =(((UINT)至大于大于5)^ 1) - =;&LT;至;
返回uppermask - (1U&LT;&LT;从);
的 uppermask
或者需要并移到它由左
(像往常一样),或者它需要一个0并且将它留下(由不要紧的量,因为它是一个的移位0),如果来== 32
。但它是一种奇怪的,使用更多的操作。
要举3个例子,即给予零,当你在操作规模以上换档的换档会解决这个问题很容易。不幸的是,那种转变是不是太普通了。
Let's take int
as an example:
int SetBitWithinRange(const unsigned from, const unsigned to)
{
//To be implemented
}
SetBitWithinRange
is supposed to return an int
in which all and only the bits starting at bit from
to bit to
are set, when from is smaller
than to
and both are in the range of 0
to 32
.
e.g.:
int i = SetBitWithinRange(2,4)
will result in i
having the value of 0b00...01100
Here are some ways. First, some variants of "set n
bits, then shift by from
". I'll answer in C# though, I'm more familiar with it than I am with C. Should be easy to convert.
uint nbits = 0xFFFFFFFFu >> -(to - from);
return nbits << from;
Downside: can't handle an empty range, ie the case where to <= from
.
uint nbits = ~(0xFFFFFFFFu << (to - from));
return nbits << from;
Upside: can handle the case where to = from
in which case it will set no bits.
Downside: can't handle the full range, ie setting all bits.
It should be obvious how these work.
Alternatively, you can use the "subtract two powers of two" trick,
(1u << to) - (1u << from)
Downside: to
can not be 32, so you can never set the top bit.
Works like this:
01000000
^^^^^^ "to" zeroes
100
^^ "from zeroes"
-------- -
00111100
To the right of the 1 in the "from" part, it's just zeroes being subtracted from zeroes. Then at the 1 in the "from" part, you will either subtract from a 1 (if to == from
) and get 0 as a result, or you'll subtract a 1 from a 0 and borrow all the way to the 1 in the to
part, which will be reset.
All true bitwise methods that have been proposed at the time of writing have one of those downsides, which raises the question: can it be done without downsides?
The answer is, unfortunately, disappointing. It can be done without downsides, but only by
- cheating (ie using non-bitwise elements), or
- more operations than would be nice, or
- non-standard operations
To give an example of 1, you can just pick any of the previous methods and add a special case (with an if
or ternary operator) to work around their downside.
To give an example of 2: (not tested)
uint uppermask = (((uint)to >> 5) ^ 1) << to;
return uppermask - (1u << from);
The uppermask
either takes a 1 and shifts it left by to
(as usual), or it takes a 0 and shifts it left (by an amount that doesn't matter, since it's 0 that's being shifted), if to == 32
. But it's kind of weird and uses more operations.
To give an example of 3, shifts that give zero when you shift by the operand size or more would solve this very easily. Unfortunately, that kind of shift isn't too common.
这篇关于C:最有效的方法来设置一个变量内的范围内的所有位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!