【问题标题】:Convert unsigned byte to signed byte将无符号字节转换为有符号字节
【发布时间】:2011-10-21 10:46:06
【问题描述】:

有没有一种简单而优雅的方法可以在 java 中将无符号字节值转换为有符号字节值?例如,如果我只有 int 值 240(二进制(24 位 + 11110000)= 32 位),我怎样才能得到这个 int 的有符号值?

【问题讨论】:

    标签: java byte unsigned signed


    【解决方案1】:
    public int getUnsignedByte(byte[] bytes, int offset) {
        return (bytes[offset] & 0xFF);
    }
    

    应该做的工作。

    【讨论】:

      【解决方案2】:

      以下是无符号字节值的存储和转换方法:

      byte b = (byte) 144; // binary value = 10010000
      

      如果您将 b 转换为 int,会发生以下情况:

      int i = b;
      System.out.println("value: "+i);  
      System.out.println("binary: " + Integer.toBinaryString(i));
      

      输出:

      value: -112 <- Incorrect value
      binary: 11111111111111111111111110010000 
      

      为什么会这样?字节用 Java 签名,b 为负数,因此强制转换操作用左侧的 1 填充结果 int。 More on java data formats

      那么我们如何从 -112 恢复到正确的 144 值呢?我们需要一个 32 位的 bitmask,我们可以使用 int 创建它:

      int mask = 0x000000FF; // This is often shortened to just 0xFF
      

      现在我们可以使用按位&amp; 运算符将最左边的 24 位“清零”,只留下我们原来的 8 位。

      int unsignedValue = b & mask; // value = 144
      

      我们的原始值 144 已经恢复,可以安全地转换回一个字节:

      byte original = (byte) unsignedValue;
      

      【讨论】:

        【解决方案3】:

        Java 没有无符号值,char 除外。考虑一下这个 sn-p:

        byte val = (byte)255;
        System.out.println(String.valueOf(val));
        

        结果将为 -1,因为最低 8 位已复制到字节变量中。

        【讨论】:

        • 我明白你的意思。 Java 中的 int 是 32 位,所以最低 8 位被复制,对吗?
        • 是的。 “最低”是指具有最低位置值 (2^n) 的位。因此,位置值为 2^0 - 2^7 的位被复制,但值为 2^8 或更高的位被丢弃。既然是java,就不用担心字节顺序了。
        • 另外,如果你想对无符号值进行处理,只需按照@ostefano 所写的方式进行 - 无论如何,java 都会在内部对整数、短裤和字节进行整数运算。
        • “Java 没有无符号值。”:不正确。 char 未签名。
        【解决方案4】:

        在 Java 中,除char 之外的所有基本类型都已签名。你不能有一个无符号字节。 您唯一可以做的就是将无符号字节转换为 int,以便您可以读取其正确值:

        int a = b & 0xff
        

        如果你想在字节类型中存储一个无符号字节值,你显然可以,但是每次你需要“处理”它时,只要记得再次转换它,如上所示。

        【讨论】:

        • 这会有什么影响?这是否仅仅意味着如果 b 是 32 位 int,那么 11111111 将复制最低 8 位?谢谢
        • 对不起,我忘了说“b”是保存在有符号字节类型(唯一可用)中的无符号字节。您始终可以将无符号字节存储为有符号字节类型,但每次需要进行数学运算时都需要执行上述转换。如果您只需要检查它的位,则不需要。
        • 我仍然不支持你。为什么你和字节 b 用 0xff?
        • 这意味着您将值向上转换为另一种类型(您不能将 0xFF 分配给 java 中的字节变量),并丢弃除最右边的 8 个位(存储值的位置)之外的所有位。
        • “在 Java 中,所有原始类型都已签名。”:不正确。 char 未签名。
        【解决方案5】:

        Java 仅支持带符号的字节,因此无论何时您将一个值放入一个字节中,它都会被假定为带符号的。

        byte b = (byte) 240;
        

        但是,如果您想存储无符号字节,则需要自己处理。 (即Java不支持它,但你可以做到)

        对于像 +, -, *, >>, ==, !=, ~ 这样的操作你不需要改变任何东西,对于像 这样的操作你需要做一些小的调整,并且对于 /, % 之类的操作,您需要使用更大的数据类型。

        一种常见的替代方法是使用更大的数据类型,例如 int 来存储 0 - 255 之间的值。这样做并没有太大的缺点。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-12
          • 1970-01-01
          • 2018-04-07
          • 2017-10-01
          • 1970-01-01
          • 2013-07-11
          • 2018-05-25
          • 2023-04-01
          相关资源
          最近更新 更多