我希望能够得到一份好的教程,为Java新手解释在Java中如何使用“位移”。
我总是遇到问题,但从未理解它是如何工作的。 它应该解释所有可以使用字节移位/位运算在Java中实现的操作和概念。
这只是我所指的示例(但我正在寻找解释每个可能操作的教程):
byte b = (byte)(l >> (8 - i << 3));
我希望能够得到一份好的教程,为Java新手解释在Java中如何使用“位移”。
我总是遇到问题,但从未理解它是如何工作的。 它应该解释所有可以使用字节移位/位运算在Java中实现的操作和概念。
这只是我所指的示例(但我正在寻找解释每个可能操作的教程):
byte b = (byte)(l >> (8 - i << 3));
嗯,官方Java教程位运算和移位运算符介绍了Java可用的实际操作以及如何调用它们。
如果你想知道“如何使用位移操作”,那不是Java特有的,并且由于这是一种低级技术,我不知道是否存在“可以做什么酷炫的事情”的清单。值得注意的是,通常通过位运算来提高效率往往会牺牲代码的清晰度。例如,a << 1
通常等同于a * 2
,但是可能不太容易理解。重复的异或运算可以交换两个数字而不使用临时变量,但一般来说更好的做法是使用临时变量(甚至更好的方式是编写一个实用方法)。因此,在这方面很难给出非常好的例子,因为在架构级别上您不太可能实现任何新的或深刻的东西;一切都与低级细节有关。(而且我估计,在“野外”使用位运算的许多用途都是过早优化的实例。)
1 << i
而不是(int)Math.pow(2,i)
。 - Paŭlo EbermannMath.pow
因为它声明了意图。事实上,在二进制实现整数的背景下,将幂指数设置为2的算术表达式可以使用较少的字符(和可能的CPU周期)来表示为<<
,但这只是硬件的偶然。一般情况下,位运算符应该(在我看来)仅在对象真正是字节序列,并且您正在执行散列/加密/压缩等操作时才使用,否则您将面临创建难以理解的代码的风险。 - Andrzej Doyledouble
类型上。(由于 Java 已经将 ^
用于按位/逻辑异或,我们不会得到这样的运算符。)我认为只有 1 << i
可以被允许(或许加上注释 // 2^i
或类似的说明)。 - Paŭlo Ebermann使用移位运算符时,一定要非常小心,不要重复常见的错误!
如下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
有无限多种可能的组合。但它们将由一个或多个组合构成。
>> shift right with sign extension.
>>> shift right with out sign extension.
<< shift left.
为了理解,我建议您在纸上写出二进制数字,并计算其结果。仅仅在教程中阅读并不能保证理解,尤其是如果它们到目前为止没有帮助到您。
以下是位移操作的详细信息。 有一些非直观的行为没有在官方教程中提到。例如,右操作数具有有限范围(int为0-31,long为0-63),如果超出该范围,将不会产生警告 - 它只会截断位(即%32或%64),这可能会导致与您期望的行为不同。
http://www.bogotobogo.com/cplusplus/quiz_bit_manipulation.html
以上教程提供了:
这里有一个包含多个Java实现的文件