关于c#:两个补码转换

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
new = old + 128;

宾果:


从您的示例输入中,您只需要:

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,就这些


    如果我不正确,您的问题是如何转换输入,它实际上是一个signed-byte(sbyte),但该输入存储在unsigned integer中,然后通过将其转换为零来避免负值。

    很明显,当你使用一个有符号的类型(如ubyte时,框架是在场景后面使用Two's complement,所以只要将类型转换为正确的类型,你就会使用二的补码。

    然后,一旦转换完成,就可以用一个简单的if或条件三元运算符(?:)

    下面介绍的函数将返回值EDOCX1(或从-128到-1)的0,以及值from 0 to 127the same value

    因此,如果您必须使用无符号整数作为输入和输出,那么可以使用如下所示:

    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)。