Two's complement conversion
我需要将两个补码格式的字节转换为正整数字节。范围-128到127映射到0到255。
1 | Examples: -128 (10000000) -> 0 , 127 (01111111) -> 255, etc. |
编辑以消除混淆,输入字节(当然)是0到255范围内的无符号整数。但它表示一个有符号整数,范围为-128到127,使用的是two的补码格式。例如,128(二进制10000000)的输入字节值实际上表示-128。
额外的编辑,好吧,假设我们有以下字节流0255254,1127。在two的补码格式中,它表示0,-1,-2,1,127。这我需要夹紧到0到255的范围。更多信息,请看这篇难以找到的文章:二的补充
1 |
宾果:
从您的示例输入中,您只需要:
1 2 3 | sbyte something = -128; byte foo = (byte)( something + 128); |
尝试
1 | sbyte signed = (sbyte)input; |
或
1 | int signed = input | 0xFFFFFF00; |
1 2 3 4 5 6 7 8 9 | public static byte MakeHexSigned(byte value) { if (value > 255 / 2) { value = -1 * (255 + 1) + value; } return value; } |
这是我解决这个问题的方法,对于大于8位的数字。我的示例是16位值。注意:您必须检查第一个位,看它是否为负数。
步骤:
将"~"置于变量之前,将转换为恭维。(y=y)
将s转换为二进制字符串
将二进制字符串拆分为字符数组
从最右边的值开始,加1,跟踪进位。将结果存储在字符数组中。
将字符数组转换回字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | private string TwosComplimentMath(string value1, string value2) { char[] binary1 = value1.ToCharArray(); char[] binary2 = value2.ToCharArray(); bool carry = false; char[] calcResult = new char[16]; for (int i = 15; i >= 0; i--) { if (binary1[i] == binary2[i]) { if (binary1[i] == '1') { if (carry) { calcResult[i] = '1'; carry = true; } else { calcResult[i] = '0'; carry = true; } } else { if (carry) { calcResult[i] = '1'; carry = false; } else { calcResult[i] = '0'; carry = false; } } } else { if (carry) { calcResult[i] = '0'; carry = true; } else { calcResult[i] = '1'; carry = false; } } } string result = new string(calcResult); return result; } |
1 2 | int8_t indata; /* -128,-127,...-1,0,1,...127 */ uint8_t byte = indata ^ 0x80; |
Xor MSB,就这些
如果我不正确,您的问题是如何转换输入,它实际上是一个
很明显,当你使用一个有符号的类型(如
然后,一旦转换完成,就可以用一个简单的
下面介绍的函数将返回值EDOCX1(或从-128到-1)的
因此,如果您必须使用无符号整数作为输入和输出,那么可以使用如下所示:
1 2 3 4 5 6 7 | private static uint ConvertSByteToByte(uint input) { sbyte properDataType = (sbyte)input; //128..255 will be taken as -128..-1 if (properDataType < 0) { return 0; } //when negative just return 0 if (input > 255) { return 0; } //just in case as uint can be greater than 255 return input; } |
或者,imho,您可以将输入和输出更改为最适合您的输入和输出的数据类型(sbyte和byte):
1 2 3 4 | private static byte ConvertSByteToByte(sbyte input) { return input < 0 ? (byte)0 : (byte)input; } |
所以问题是,运算的问题不是二的补码转换。他正在对一组值添加偏差,以将范围从-128..127调整到0..255。
要实际执行二的补码转换,只需将有符号值类型化为无符号值,如下所示:
1 2 | sbyte test1 = -1; byte test2 = (byte)test1; |
-1变为255。-128变为128。不过,这听起来不像是手术室想要的。他只想向上滑动一个数组,使最低的有符号值(-128)成为最低的无符号值(0)。
要添加偏差,只需执行整数加法:
1 | newValue = signedValue+128; |
我认为2s补码字节最好用以下方法来完成。可能不优雅或短,但清晰和明显。我将把它作为一个静态方法放在我的一个Util类中。
1 2 3 4 5 6 7 8 9 10 11 12 | public static sbyte ConvertTo2Complement(byte b) { if(b < 128) { return Convert.ToSByte(b); } else { int x = Convert.ToInt32(b); return Convert.ToSByte(x - 256); } } |
您可以描述一些简单的事情,比如在数字上添加一个偏差(在本例中,在有符号的数字上添加128)。