【问题标题】:java bit manipulationjava位操作
【发布时间】:2009-02-19 01:08:43
【问题描述】:
byte x = -1;
for(int i = 0; i < 8; i++)
{
    x = (byte) (x >>> 1);
    System.out.println("X: " + x);
}

据我了解,java 以二进制补码形式存储数据,即 -1 = 11111111(根据维基百科)。

另外,来自 java 文档: “位模式由左侧操作数给出,而要移位的位置数由右侧操作数给出。无符号右移位运算符“>>>”将零移到最左边的位置,而最左边的位置在后面“>>”取决于符号扩展。“

这意味着 >>> 每次都会将 0 移到最左边。所以我希望这段代码是

迭代:x的位表示

0: 11111111

1:01111111

2:00111111

3: 00011111

...等等

但是,我的输出始终是 X: -1,这意味着(我猜)>>> 将符号位放在最左边的位置。所以我然后尝试>>,结果相同。

发生了什么事?我希望我的输出是:X:-1,x:127,x:63,等等。

【问题讨论】:

  • 这是 Java Puzzlers 中的问题之一。

标签: java bit-manipulation byte


【解决方案1】:

在发明 Java 时认为应该对字节进行签名的人应该取出并用湿芹菜棒殴打直到他们哭泣 :-)

您可以通过强制转换为 int 并确保永远不会将 1 移到最高位来做您想做的事情,如下所示:

byte x = -1;
int x2 = ((int)x) & 0xff;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X: " + x2);
}

您的特殊问题是因为 >>> 正在转换为一个 int 来进行移位,然后您将它转换回一个字节,如下所示:

byte x = -1;
int x2 = ((int)x) & 0xff;
int x3;
int x4 = x2;
for(int i = 0; i < 8; i++)
{
    x2 = (x2 >>> 1);
    System.out.println("X2: " + x2);
    x3 = (x >>> 1);
    x = (byte)x3;
    x4 = (x4 >>> 1);
    System.out.println("X: " + x3 + " " + x + " " + x4);
}

哪些输出:

X2: 127
X: 2147483647 -1 127
X2: 63
X: 2147483647 -1 63
X2: 31
X: 2147483647 -1 31
X2: 15
X: 2147483647 -1 15
X2: 7
X: 2147483647 -1 7
X2: 3
X: 2147483647 -1 3
X2: 1
X: 2147483647 -1 1
X2: 0
X: 2147483647 -1 0

您可以清楚地看到 x 和 x3 不起作用(即使 x3 正确移动,将其转换回 x 中的字节又会将其设置为 -1)。 x4 完美运行。

【讨论】:

  • 虽然这确实有效(感谢您的帮助),但它并没有向我解释为什么我的代码不起作用。
  • +1 表示芹菜评论。我从来没有遇到过我想要一个字节被签名的情况......
【解决方案2】:

记住:

  • 按位运算的操作数总是提升为至少一个 int
  • 强制转换总是涉及符号扩展

因此,当您执行 (x >>> n) 时,即使您将 x 定义为字节,出于移位的目的,它也会首先转换为 int。如果要转换的字节为负数,则添加以使其成为 int 的所有“额外位”(因此,结果 int 的最左边 24 位)将设置为 1。或者换一种方式,如果原始byte 是 -1,你实际移动的东西是 -1 作为 int,即所有 32 位设置为 1 的 32 位数字。将其右移 1-8 位仍然会导致在底部的 8 位都设置为 1,因此当你转换回一个字节时,你最终会得到一个所有 8 位都设置为 1 的字节,或者换句话说,一个字节值为 -1。

【讨论】:

    【解决方案3】:

    对此我不确定。但是,我的猜测是

    x >>> 1 
    

    从字节提升为int,因为文字“1”是一个int。那么你观察到的东西是有道理的。

    【讨论】:

    • 我不这么认为.. 我更改了代码以确保它没有被提升为 int: byte x = -1; for(int i = 0; i > (byte)1); System.out.println("X:" + x); } 输出是一样的,X: -1 每次
    • 这无济于事 - 当然,您将 x 和 1 转换为字节,但 Java 在应用右移运算符之前会自动将它们转换回整数。据我所知,没有办法直接对字节应用位移。
    【解决方案4】:

    我不知道为什么它不起作用,但清除最高位的一种简单方法是与(二进制)0111111 一起使用:

    x = (byte) (x >>> 1) & 0x7F;
    

    【讨论】:

      【解决方案5】:

      问题是,如前所述(很久以前),x 在进行移位之前被向上转换为 int(符号扩展)。
      进行“位到位”转换应该会有所帮助:

      byte x = -1;
      for(int i = 0; i < 8; i++)
      {
          x = (byte) ((x & 0xFF) >>> 1);
          System.out.println("X: " + x);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-07
        • 2014-08-07
        相关资源
        最近更新 更多