二进制补码转换

15

我需要将以二进制补码表示的字节转换为正整数字节。范围为-128到127映射到0到255。

Examples: -128 (10000000) -> 0 , 127 (01111111) -> 255, etc.
编辑:为了澄清混淆,输入字节当然是无符号整数,范围在0到255之间。但是,它使用二进制补码格式代表范围内的有符号整数-128到127。例如,输入字节值为128(二进制10000000)实际上表示-128。 额外编辑:好的,假设我们有以下字节流0、255、254、1、127。在二进制补码格式中,这代表0、-1、-2、1、127。我需要将其限制在0到255的范围内。更多信息请查看这篇难以找到的文章:二进制补码

2
byte 不是有符号的,你在尝试做什么? - leppie
我仍然不完全确定这里尝试的是什么。要么这是所有答案给你的方式,要么你对二进制补码表示理解有误。 - leppie
10个回答

8

根据您的样例输入,您只是想要:

sbyte something = -128;

byte foo = (byte)( something + 128);

3
但是你如何在0到255范围内表示-1呢? - leppie

7
new = old + 128;

干得好 :-)


12
因为我找不到“bingo”关键字,所以我已经编辑了你的答案以使其更易读 :-) - paxdiablo
1
“old” 是原始的字节值还是转换后的值?如果它是原始的字节值,那么这会得出错误的答案。如果它是后者,那么我正在询问的就是这个过程。 - Yehonatan

3

尝试

sbyte signed = (sbyte)input;

或者

int signed = input | 0xFFFFFF00;

2
    public static byte MakeHexSigned(byte value)
    {
        if (value > 255 / 2)
        {
            value = -1 * (255 + 1) + value;
        }

        return value;
    }

2

我认为使用以下方法最好完成2s补码字节。也许不太优雅或简短,但是清晰明了。我会将其放在我的实用程序类的静态方法中。

public static sbyte ConvertTo2Complement(byte b)
{
    if(b < 128)
    {
        return Convert.ToSByte(b);
    }
    else
    {
        int x = Convert.ToInt32(b);
        return Convert.ToSByte(x - 256);
    }
}

1
所以问题在于,OP的问题并不是二进制补码转换。他正在为一组值添加一个偏差,以将范围从-128..127调整为0..255。
要实际执行二进制补码转换,只需将有符号值强制转换为无符号值,如下所示:
sbyte test1 = -1;
byte test2 = (byte)test1;

-1变成了255。-128变成了128。虽然如此,这似乎并不是OP想要的。他只是想将数组向上滑动,以便最低的有符号值(-128)变成最低的无符号值(0)。

要添加偏差,只需进行整数加法:

newValue = signedValue+128;

1

如果我理解正确,您的问题是如何将输入转换为实际上是一个signed-bytesbyte),但该输入存储在一个unsigned integer中,并且通过将它们转换为零来避免负值。

要明确,当您使用有符号类型(例如ubyte)时,框架在幕后使用Two's complement,因此只需将其强制转换为正确的类型即可使用two's complement。

然后,一旦完成了这种转换,您可以使用简单的if或条件三元运算符(?:)夹住负值。

下面呈现的函数将返回0,对于值从128到255(或从-128到-1),以及对于值从0到127相同值

所以,如果你必须使用无符号整数作为输入和输出,你可以使用类似这样的代码:

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;
}

或者,依我之见,您可以将输入和输出更改为最适合您的输入和输出数据类型(sbyte 和 byte):
private static byte ConvertSByteToByte(sbyte input)
{
    return input < 0 ? (byte)0 : (byte)input;
}

1
以下是我针对这个问题的解决方案,适用于大于8位的数字。我的示例是针对16位值的。注意:您必须检查第一位,以确定它是否为负数。
步骤:
  1. 在变量前面加上'~'将#转换为补码。(例如:y = ~y)

  2. 将#s转换为二进制字符串

  3. 将二进制字符串分解成字符数组

  4. 从最右边的值开始,加1,跟踪进位。将结果存储在字符数组中。

  5. 将字符数组转换回字符串。

    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
int8_t indata; /* -128,-127,...-1,0,1,...127 */
uint8_t byte = indata ^ 0x80;

xor MSB,就是这样


2
那看起来不像是C#。 - reggaeguitar
这并没有实现原帖中所述的目标。他想让-128变成0。这只是一个整数加法。结果=signedbyte + 128; - Tom Wilson

0

你可能正在描述一些简单的事情,比如给你的数字添加一个偏置(在这种情况下,将128添加到有符号数字中)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接