Java位移教程?

45

我希望能够得到一份好的教程,为Java新手解释在Java中如何使用“位移”。

我总是遇到问题,但从未理解它是如何工作的。 它应该解释所有可以使用字节移位/位运算在Java中实现的操作和概念。

这只是我所指的示例(但我正在寻找解释每个可能操作的教程):

byte b = (byte)(l >> (8 - i << 3));

9
这是“位移”而不是“字节移位”。 - Oded
谢谢,我更新了标题(你更快;-) - Markus
2
你可能想看一下这个页面: https://dev59.com/Q3VC5IYBdhLWcg3w7V73 - Mike Kwan
对于所有感兴趣的人,除了下面的答案之外,Mike提供的链接绝对值得一读! - Markus
8个回答

33

嗯,官方Java教程位运算和移位运算符介绍了Java可用的实际操作以及如何调用它们。

如果你想知道“如何使用位移操作”,那不是Java特有的,并且由于这是一种低级技术,我不知道是否存在“可以做什么酷炫的事情”的清单。值得注意的是,通常通过位运算来提高效率往往会牺牲代码的清晰度。例如,a << 1通常等同于a * 2,但是可能不太容易理解。重复的异或运算可以交换两个数字而不使用临时变量,但一般来说更好的做法是使用临时变量(甚至更好的方式是编写一个实用方法)。因此,在这方面很难给出非常好的例子,因为在架构级别上您不太可能实现任何新的或深刻的东西;一切都与低级细节有关。(而且我估计,在“野外”使用位运算的许多用途都是过早优化的实例。)


7
另一方面,在范围为0到31的情况下,我更喜欢使用1 << i而不是(int)Math.pow(2,i) - Paŭlo Ebermann
13
@Paŭlo:实际上这是我观点的一个很好的例子。虽然Java很冗长,但在这里我更喜欢使用Math.pow因为它声明了意图。事实上,在二进制实现整数的背景下,将幂指数设置为2的算术表达式可以使用较少的字符(和可能的CPU周期)来表示为<<,但这只是硬件的偶然。一般情况下,位运算符应该(在我看来)仅在对象真正是字节序列,并且您正在执行散列/加密/压缩等操作时才使用,否则您将面临创建难以理解的代码的风险。 - Andrzej Doyle
2
如果存在一个整数幂运算符,我也会更喜欢它。但是实际上并没有这样的运算符,Math.pow 定义在 double 类型上。(由于 Java 已经将 ^ 用于按位/逻辑异或,我们不会得到这样的运算符。)我认为只有 1 << i 可以被允许(或许加上注释 // 2^i 或类似的说明)。 - Paŭlo Ebermann
1
位运算对于像BufferedImages创建的RGB颜色之类的东西非常有用。 - Thijser
就“酷操作”而言,我发现最方便的是异或交换 - 它可以让您在不必分配更多内存的情况下切换两个变量的值。在Java中,它将是X = X^Y; Y = Y^X; X = X^Y; 应用可能似乎有限,但如果您正在处理具有内存限制的嵌入式系统,或者希望严格优化性能,则它具有其用途。 - mdhansen

15

使用移位运算符时,一定要非常小心,不要重复常见的错误!

如下SO帖子所建议的,被采纳答案的作者提到:

"在某些语言中,将移位操作符应用于比int类型更小的任何数据类型时,自动调整操作数大小为int。"

在对字节进行操作时,这一点绝对是需要记住的,否则你可能会得到意想不到的结果(正如我所遇到的情况)。

给定一个具有以下位模式的字节:

1001 0000

当我尝试将一个int值左移4位,并赋值给另一个int时,例如:

int value = byteValue >>> 4;

我期望会拥有:

0000 1001   (or a value of 9)

但我会得到一个巨大的数字!这是因为在位移操作之前,byteValue被强制转换为int类型,结果可能会像这样:

1111 1111 1111 1111 1111 1111 1001

1
一个不错的解决方法是创建一个位掩码 (在这个例子中,0000 0000 0000 0000 0000 0000 1111),并用该掩码与结果进行“&”操作,以强制删除可能存在的扩展前导 1。 - mdhansen

13

有无限多种可能的组合。但它们将由一个或多个组合构成。

>> shift right with sign extension.
>>> shift right with out sign extension.
<< shift left.

为了理解,我建议您在纸上写出二进制数字,并计算其结果。仅仅在教程中阅读并不能保证理解,尤其是如果它们到目前为止没有帮助到您。


9

我发现这里有一个简单但明确的教程,与IT技术有关,特别是Java编程中的位运算和位移操作。 这里


2
链接已经失效。 - eddyrokr

5

这不是一份教程,但我有一个关于Java位运算的个人函数库,您可以自由地研究!

另外,如果您在谷歌上搜索"位运算技巧",您会找到很多资料。其中许多是用C/C++编写的,但通常可以轻松转换为Java,因为大部分语法都是相同的。


5

以下是位移操作的详细信息。 有一些非直观的行为没有在官方教程中提到。例如,右操作数具有有限范围(int为0-31,long为0-63),如果超出该范围,将不会产生警告 - 它只会截断位(即%32或%64),这可能会导致与您期望的行为不同。


3
这个网站似乎提供了一个非常好的关于位操作可以做什么的教程(因此不特定于Java,但由于很容易翻译)。

http://www.bogotobogo.com/cplusplus/quiz_bit_manipulation.html

以上教程提供了:

  • 位运算
  • 设置和清除位
  • 显示带位的整数
  • 十进制转十六进制
  • 整数中设置的位数(1的数量)
  • 整数的位设置位置
  • 使用位操作进行原地整数交换
  • 将整数A转换为整数B所需的位数
  • 交换整数中奇数位和偶数位
  • (n & (n-1) == 0) 检查什么?
  • 二进制补码
  • 翻转整数的第n位
  • 浮点数位模式
  • 整数的位模式是否回文

这里有一个包含多个Java实现的文件

http://geekviewpoint.com/


2

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