C:最有效的方法来设置一个变量内的范围内的所有位 [英] C: Most efficient way to set all bits in a range within a variable

查看:83
本文介绍了C:最有效的方法来设置一个变量内的范围内的所有位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们来 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. 欺骗(即使用非按位元素),或

  2. 的操作量超出就好了,或者

  3. 不规范操作

要举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 intin 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

  1. cheating (ie using non-bitwise elements), or
  2. more operations than would be nice, or
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆