C# 将一个字节的前n位与另一个字节的最后8-n位合并

C# 将一个字节的前n位与另一个字节的最后8-n位合并,c#,java,C#,Java,如何将一个字节的前n位与另一个字节的最后8-n位合并 我知道从第一位中选取3位,从第二位中选取5位(这是我在DES加密算法中观察到的) zByte=(xByte&0xE0)|(yByte&0x1F)但我不知道为什么在这种情况下需要使用0XE0和0X1F。因此,我试图了解每一位的细节 在C#中,这将类似于: int mask = ~((-1) << n); var result = (x & ~mask) | (y & mask); int mask

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

我知道从第一位中选取3位,从第二位中选取5位(这是我在DES加密算法中观察到的)
zByte=(xByte&0xE0)|(yByte&0x1F)
但我不知道为什么在这种情况下需要使用0XE0和0X1F。因此,我试图了解每一位的细节

在C#中,这将类似于:

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

int mask=~(-1)听起来你好像不明白布尔运算是如何工作的?如果这是你的问题,它的工作原理如下:

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。在完成对父操作数的计算之后sis然后我们将获得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
如果您了解这一点以及布尔逻辑是如何工作的,那么您可以使用的答案。

在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;
}
publicstaticvoidmain(字符串[]args){
字节a=15;
字节b=16;
字符串mergedValue=merge(4,a,b);
System.out.println(合并值);
}
公共静态字符串合并(int n,字节a,字节b){
字符串mergedString=“”;
字符串sa=Integer.toBinaryString(a);
字符串sb=整数。toBinaryString(b);
如果(n>sa.length()){
对于(int i=0;isb.length()){

对于(int i=0;i这些数字(0xE0和0x1F)背后的数学非常简单。首先,我们利用了
0&
始终等于
0
1&
始终等于
这一事实


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

C#
Java
?选择一种。还有,到目前为止你都尝试了什么?合并意味着连接,或者?或者?我知道Java和C#,无论用哪种语言我都会得到答案。我可以用其他语言解释它。我知道下面类似的方法,从第一位选择3位,从第二位选择5位(我在DES加密算法中观察到)zByte=(xByte&0xE0)|(yByte&0x1F);但我不知道为什么在这种情况下需要使用E0和1F的背后的数学原因。所以我试图理解每一位的细节。@RajeshSubramanian我指的是连接。这不是连接。你可以这样制作掩码:
int mask=0xff>>n;
@LorentzVedeler假设示例为n=17,这将不起作用。Al因此,对于全宽度操作,它需要无符号-在Java上有问题。但是:一个选项本身应该可以很好地工作。会更新…更好吗?是的,这很好。顺便说一句,Java有一个无符号右移,所以您也可以使用稍微不同的属性(“镜像”)执行
-1>-n
(在C#中稍微详细一些)从某种意义上说,属性)。你好,兄弟……我知道真值表,我知道什么是十六进制、二进制和任何其他格式。我想你不明白我的问题。你能告诉我如何从一个字节中提取前2位或后2位吗?然后我会从那里开始…@SudhakarChavali要提取位,你通常是“和”带着面具,就像每个人都在说的那样……这很可能是我见过的执行位运算最不必要的复杂方式。计算机被设计成与位一起工作——把所有事情都当作字符串来做本质上也被称为“做错了”.好的,谢谢你宝贵的回复,我们将努力提高我的钻头操作技能。