【问题标题】:Two's complement conversion二进制补码转换
【发布时间】:2011-04-18 06:29:23
【问题描述】:

我需要将二进制补码格式的字节转换为正整数字节。 范围 -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 的范围内。有关更多信息,请查看这篇很难找到的文章:Two's complement

【问题讨论】:

  • byte 没有签名,你想做什么?
  • 我仍然不完全确定这里尝试了什么。要么它是所有答案给你的方式,要么你错误地理解了 2 的补码表示。

标签: c# twos-complement


【解决方案1】:

所以问题在于 OP 的问题实际上并不是二进制补码转换。他正在向一组值添加 偏差,以将范围从 -128..127 调整到 0..255。

要实际进行二进制补码转换,您只需将有符号值类型转换为无符号值,如下所示:

sbyte test1 = -1;
byte test2 = (byte)test1;

-1 变为 255。-128 变为 128。不过,这听起来不像 OP 想要的。他只是想把一个数组向上滑动,使最小的有符号值(-128)变成最小的无符号值(0)。

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

newValue = signedValue+128;

【讨论】:

    【解决方案2】:

    这是我对这个问题的解决方案,适用于大于 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;
      
      }
      

    【讨论】:

      【解决方案3】:

      我相信 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);
          }
      }
      

      【讨论】:

        【解决方案4】:
        int8_t indata; /* -128,-127,...-1,0,1,...127 */
        uint8_t byte = indata ^ 0x80;
        

        xor MSB,就是这样

        【讨论】:

        • 在我看来这不像 C#
        • 这并没有实现 OP 声明的目标。他希望 -128 变为 0。这只是一个整数加法。结果 = 有符号字节 + 128;
        【解决方案5】:
            public static byte MakeHexSigned(byte value)
            {
                if (value > 255 / 2)
                {
                    value = -1 * (255 + 1) + value;
                }
        
                return value;
            }
        

        【讨论】:

          【解决方案6】:

          试试

          sbyte signed = (sbyte)input;
          

          int signed = input | 0xFFFFFF00;
          

          【讨论】:

            【解决方案7】:

            如果我没有正确理解,你的问题是如何转换输入,这实际上是一个signed-byte (sbyte),但该输入存储在一个unsigned integer 中,然后还通过转换它们来避免负值归零。

            需要明确的是,当您使用带符号类型(如 ubyte)时,框架在后台使用 Two's complement,因此只需转换为正确的类型,您将使用二进制补码。

            然后,完成转换后,您可以使用简单的if 或条件三元运算符 (?:) 来限制负值。

            下面介绍的函数将返回 0from 128 to 255(或从 -128 到 -1),the same valuefrom 0 to 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;
            }
            

            【讨论】:

              【解决方案8】:
              new = old + 128;
              

              宾果游戏:-)

              【讨论】:

              • 因为我找不到 bingo 关键字,我已经编辑了你的答案以提高可读性:-)
              • “旧”是原始字节值还是它的转换?如果它是原始字节值,那么这给出了错误的答案。如果是后者,那么这就是我所要求的过程。
              【解决方案9】:

              您可以描述一些简单的事情,例如向您的号码添加偏差(在本例中,将 128 添加到已签名的号码)。

              【讨论】:

                【解决方案10】:

                从您想要的示例输入中:

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

                【讨论】:

                • @Yehonatan:但是你想如何在 0 到 255 范围内表示 -1?
                猜你喜欢
                • 2013-09-28
                • 1970-01-01
                • 2016-07-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-03-01
                • 2014-11-15
                相关资源
                最近更新 更多