3

我们需要想出一个在 int 输出中设置 4 位半字节的方法,应该像这样:

 setNibble(0xAAA5, 0x1, 0); // => 0xAAA1
 setNibble(0x56B2, 0xF, 3); // => 0xF6B2

这是我写的...

但是有一些我无法弄清楚的错误

setNibble(FFFF, 0, 0): Expected: FFF0 Result: FF00 
setNibble(FFFF, 6, 1): Expected: FF6F Result:  6FF 
setNibble(1312, E, 1): Expected: 13E2 Result:  E12 

更新:我已经放下代码以防万一。但基本上答案真的很清楚,上面有很多很好的答案。

4

3 回答 3

4

你非常接近;

    public static int setNibble(int num, int nibble, int which)
    {
        int output;
        if(which ==0)
        {
            output = (num & /*65280*/ 0xFFFFFFF0 ) | nibble;
        }
        else
        {
            int shiftNibble = nibble << (4*which) ;
            int shiftMask = 0x0000000F << (4*which) ;
            output = (num & ~shiftMask) | shiftNibble ;
        }
        return output;
    }

实际上,您可以以which == 0单独处理大小写为代价来简化代码。事实上,你是在if用一个换班和一个not。根本没有太大区别,代码更清晰,更优雅。

    public static int setNibble(int num, int nibble, int which) {
        int shiftNibble= nibble << (4*which) ;
        int shiftMask= 0x0000000F << (4*which) ;
        return ( num & ~shiftMask ) | shiftNibble ;
    }

掩码的想法是完全清除半字节将在结果中占据的相同 4 个位置。否则,该位置将在半字节为零的那些位中包含垃圾。例如

    // Nibble           77776666555544443333222211110000
    num=              0b01001010111101010100110101101010 ;
    nibble=           0b0010 ;  // 2
    which=            3 ;
    shiftNibble=      0b00000000000000000010000000000000 ;
    shiftMask=        0b00000000000000001111000000000000 ;
    num=              0b01001010111101010100110101101010 ;
    ~shiftMask=       0b11111111111111110000111111111111 ;  
    num & ~shiftMask= 0b01001010111101010000110101101010 ;
    //                                  ~~~~  Cleared!
    ( num & ~shiftMask ) 
      | nibble        0b01001010111101010010110101101010 ;
    //                                  ~~~~  Fully set; no garbage!
于 2013-09-03T03:58:24.120 回答
3

这就是我的做法:

public static int setNibble(int word, int nibble, int whichNibble)
{
    int shift = whichNibble * 4;
    return (word & ~(0xf << shift)) | (nibble << shift);
}

让我们分解一下:

  • shift是将半字节的 4 位放置在整数内的正确位置需要移动的位数。如果要定位半字节 0,shift则为 0;半字节 1 是 4;8 表示半字节 2;等等。
  • (0xf << shift)是一个二进制掩码,其中半字节占据的每一位都有 1。如果您想要半字节 1,这将是(为简洁起见,使用 16 位整数)。0b0000 0000 1111 0000
  • ~(0xf << shift)是保留在原始参数中的二进制掩码。假设您想再次替换 nibble 1,则此掩码为0b1111 1111 0000 1111.
  • word & ~(0xf << shift)清除我们要替换的位word
  • (nibble << shift)是您正在设置的半字节的二进制模式。如果您的 nibble 值是0b1001,一旦移动,它就会变成。0b0000 0000 1001 0000
  • 表达式中间的二进制或组合初始值,现在我们要设置的位已被清除,移位的半字节得到最终解决方案。
于 2013-09-03T04:09:12.987 回答
0

你移动了错误的量。您需要为每个“which”移动 4 位;那么您需要替换该位置的位(首先将这些位设置为零,然后与移位的半字节或)。像这样的东西:

shiftIt = 4 * which;
mask = 0xf << shiftIt;
num = num & ~mask;
num = num + (n << shiftIt);

您应该能够从这里找出详细信息。

于 2013-09-03T03:58:01.307 回答