开发者

returns x with the n bits that begin at position p set to the rightmost n bits of y, leaving other bits unchanged

开发者 https://www.devze.com 2023-03-21 10:22 出处:网络
my solution get the rightmost n bits of y a = ~(~0 << n) & y clean the n bits 开发者_JS百科of x beginning from p

my solution

get the rightmost n bits of y
a = ~(~0 << n) & y

clean the n bits 开发者_JS百科of x beginning from p
c = ( ~0 << p | ~(~0 << (p-n+1))) & x

set the cleaned n bits to the n rightmost bits of y
c | (a << (p-n+1))

it is rather long statements. do we have a better one?

 i.e
x = 0 1 1 1 0 1 1 0 1 1 1 0
p = 4
y = 0 1 0 1 1 0 1 0 1 0 
n = 3

the 3 rightmost bits of y is 0 1 0 
it will replace x from bits 4 to bits 2 which is 1 1 1


I wrote similar one:

 unsigned setbits (unsigned x, int p, int n, unsigned y)
{
  return (x & ~(~(~0<<n)<<(p+1-n)))|((y & ~(~0<<n))<<(p+1-n));
}


There are two reasonable approaches.

One is yours: Grab the low n bits of y, nuke the middle n bits of x, and "or" them into place.

The other is to build the answer from three parts: Low bits "or" middle bits "or" high bits.

I think I actually like your version better, because I bet n and p are more likely to be compile-time constants than x and y. So your answer becomes two masking operations with constants and one "or"; I doubt you will do better.

I might modify it slightly to make it easier to read:

mask = (~0 << p | ~(~0 << (p-n+1)))
result = (mask & a) | (~mask & (y << (p-n+1)))

...but this is the same speed (indeed, code) as yours when mask is a constant, and quite possibly slower when mask is a variable.

Finally, make sure you have a good reason to worry about this in the first place. Clean code is good, but for something this short, put it in a well-documented function and it does not matter that much. Fast code is good, but do not attempt to micro-optimize something like this until your profiler tells you do. (Modern CPUs do this stuff very fast; it is unlikely your application's performance is bounded by this sort of function. At the very least it is "innocent until proven guilty".)


Have a look at the following descriptive code:

int setbitsKR(int x, int p, int n, int y){
    int shiftingDistance = p - n + 1,
        bitmask = (1 << n) - 1, // example, 11
        digitsOfY = (y & bitmask) << shiftingDistance, // whatever        
        bitmaskShiftedToLeft = bitmask << shiftingDistance, // 001100
        invertedBitmaskShiftedToLeft = ~bitmaskShiftedToLeft; // 110011

    // erase those middle bits of x
    x &= invertedBitmaskShiftedToLeft;

    // add those bits from y into x
    x |= digitsOfY;

    return x;
}

In short, it creates a bitmask (string of 1s), shifts them to get to that middle position of x, nukes those bits of x by &ing with a string of 0s (inverted bitmask), and finally |s that position with the right digits of y.

0

精彩评论

暂无评论...
验证码 换一张
取 消