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
现在 |
(注意 a
和 b
不会 "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 位。
对于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
现在 |
(注意 a
和 b
不会 "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 位。