Java 表达式等价

Java expression equivalence

对于Java如何:

long c = ((long)a << 32) | ((long)b & 0xFFFFFFFL);

相当于

long c = (long)a << 32
c+=b

据我了解,位掩码会返回原始数字本身,并且 OR 和加法运算不等价。那么这两个实现怎么总是给出相同的答案呢?

它们不等价(除非您限制 b 的可能值)。

例如,如果 a == 1 和 b == -1,则第一个表达式的结果为 4563402751,第二个表达式的结果为 4294967295

如果您将 b 限制为 >= 0 和 <= 0xFFFFFFF(即 2^28 - 1),它们将给出相同的结果。

(long)a << 32(假设 a 是比 long 更小的基本类型)将 a 的位向左移动 32 个位置。

因此如果 a

                          xxx....xxxxxx

(long)a << 32 是

             xxx....xxxxxx000....000000 

现在,如果您在该数字和任何非负数 int 之间执行按位或运算,您将得到与将这两个数字相加相同的结果,因为 (long)a << 32 的低 32 位是0,因此向其添加一个在其低 31 位中只有 1 位的数字与将 (long)a << 32 中所有为 1 的位和 1 中的所有位设置为 1 相同第二个数字(相当于按位或)。

让我们看看位。

假设int是1个字节(8位),long是2个字节(16位)。

a << 32 变为 a << 8 并且 0xFFFFFFFFL 变为 0xFFFFL:

左边部分((long)a << 8):

开始:

bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: a a a a a a a a a a a a a a a a

移位a << 8:

                      <-  shifted  ->
bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: a a a a a a a a 0 0 0 0 0 0 0 0

右边((long)b & 0xFFFFL):

开始:

bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: b b b b b b b b b b b b b b b b

b & 0xFFFL之后:

      <- & with 0  -> <- & with 1  ->
bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: 0 0 0 0 0 0 0 0 b b b b b b b b

现在 |(注意 ab 不会 "touch" 彼此!):

bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: 0 0 0 0 0 0 0 0 b b b b b b b b

bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: a a a a a a a a 0 0 0 0 0 0 0 0

给出:

bits: 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
data: a a a a a a a a b b b b b b b b

请注意,这可能仅适用于部分值(尝试正数和负数),但其背后的逻辑正如我所说。

如果操作数没有任何公共位,则按位或等同于加法。

例如:

0x123456780000000 + 0x12345678 = 0x1234567812345678
0x123456780000000 | 0x12345678 = 0x1234567812345678

如果你只是向左移动 a 32 位,那么右边就会有 32 个零位。假设 b 只有 32 位,您可以安全地执行 OR 而不是加法。

((long)b & 0xFFFFFFFFL)b 中提取最低有效的 32 位。 ((long)a << 32) 创建一个 long,其中最低有效的 32 位为 0。这样,OR 相当于 +=.

不过我不确定这是否也适用于 b 的负值(二进制补码)。

请注意 Java 中的 long 有 64 位。