0

如何将一个字节的前 n 位与另一个字节的后 8-n 位合并?

我知道像下面这样从第一位选择 3 位,从第二位选择 5 位(我在 DES 加密算法中观察到)
zByte=(xByte & 0xE0) | (yByte & 0x1F);
但我不知道为什么我们需要在这种情况下使用 0XE0 和 0X1F 背后的数学。所以我试图了解每一位的细节。

4

4 回答 4

5

在 C# 中,这将类似于:

    int mask = ~((-1) << n);
    var result = (x & ~mask) | (y & mask);

即,我们构建一个掩码,即(对于 n = 5)000....0011111:,然后我们将(&)一个操作数与该掩码组合,将另一个操作数与掩码的~)组合,并将它们组合(|)。

您也可以仅使用移位操作(完全避免使用掩码)更快地做一些事情 - 但前提是数据可以被视为unsigned(因此 Java 可能会在这里遇到困难)。

于 2013-10-10T10:33:57.033 回答
2

听起来你不明白布尔算术是如何工作的?如果这是您的问题,它的工作原理如下:

0xEO并且0x1F是数字的十六进制表示。如果我们将这些数字转换为二进制,它们将是:

0xE0 = 11100000
0x1F = 00011111

另外 & (and) 和 | (or) 是按位逻辑运算符。要理解逻辑运算符,首先要记住 1 = true 和 0 = false。

& 的真值表是:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

真值表| 是:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

因此,让我们逐个分解您的方程式。首先,我们将首先评估括号中的代码。我们将遍历二进制中的每个数字,对于 & 运算符,如果每个操作数在相同的位上都有一个 1,我们将返回 1。如果任何一个数字有一个 0,那么我们将返回 0。在我们完成对操作数的求值后括号中我们将得到 2 个结果数字并应用 | 操作员一点一点。如果任一数字在相同的位位置有 1,我们将返回 1。如果两个数字在相同的位位置有 0,我们将返回 0。

为了讨论,让我们说

xByte = 255 or (FF in hex and 11111111 in binary)
yByte = 0 or (00 in hex and 00000000 in binary)

当你应用 & 和 | 我们将一次比较每个位的运算符:

zByte = (xByte & 0xEO) | (yByte & 0x1F)

变成:

zByte = (11111111 & 11100000) | (00000000 & 00011111)
zByte = 111000000 | 00000000
zByte = 11100000

如果您了解这一点以及布尔逻辑的工作原理,那么您可以使用Marc Gravell的答案。

于 2013-10-10T11:24:54.153 回答
1

这些数字(0xE0 和 0x1F)背后的数学原理非常简单。0 & <bit>首先,我们利用always equals01 & <bit>always equals的事实<bit>

0x1F 是 00011111 二进制,这意味着在对另一个字节进行 & 操作后,前 3 位将始终为 0 - 最后 5 位将与它们在另一个字节中的相同。请记住,二进制数中的每个 1 代表 2 的幂,因此,如果您想在数学上找到掩码,它将是从 x = 0 到 n-1 的 2^x 的总和。然后您可以找到相反的掩码(即 11100000)来提取前 3 位,您只需从 11111111 中减去掩码,您将得到 11100000(0xE0)。

于 2013-10-10T15:52:59.813 回答
0

在java中,

通过使用以下函数,我们可以获得第一个字节的前 n 位和第二个字节的后 8 n 位。

公共类 BitExample {

public static void main(String[] args) {
    Byte a = 15;
    Byte b = 16;
    String mergedValue=merge(4, a, b);
    System.out.println(mergedValue);
}


public static String merge(int n, Byte a, Byte b) {
    String mergedString = "";
    String sa = Integer.toBinaryString(a);
    String sb = Integer.toBinaryString(b);

    if(n>sa.length()) {
        for(int i=0; i<(n-sa.length()); i++) {
            mergedString+="0";
        }
        mergedString+=sa;
    }else{
        mergedString+=sa.substring(0, n);
    }

    if(8*n>sb.length()) {
        for(int i=0; i<(8*n-sb.length()); i++) {
            mergedString+="0";
        }
        mergedString+=sb;
    }
    return mergedString;
}

}

于 2013-10-10T11:27:46.970 回答