为了账号安全,请及时绑定邮箱和手机立即绑定

按位运算符究竟如何在Java中工作?

按位运算符究竟如何在Java中工作?

梦里花落0921 2022-09-28 14:49:57
我目前正在尝试在Java中围绕位和位移运算符。虽然它们在简化的玩具示例(基本上是正整数)中对我来说是有意义的,但是一旦涉及负数,我的理解就会崩溃,在其他一些情况下也是如此。我尝试用两个搜索引擎在互联网上搜索,我甚至检查了Java规范。我找不到任何正确描述按位和位移运算符在Java中如何工作的来源。Java标准库中特别让我感到困惑的一个函数是 。来自 OpenJdk 的源代码如下所示(LGPLv2 具有类路径异常),并在爪哇文档中摘录:java.lang.Integer.toUnsignedLong(int)/** * Converts the argument to a {@code long} by an unsigned * conversion.  In an unsigned conversion to a {@code long}, the * high-order 32 bits of the {@code long} are zero and the * low-order 32 bits are equal to the bits of the integer * argument.    */public static long toUnsignedLong(int x) {    return ((long) x) & 0xffffffffL;}根据上面复制的官方文档,“长整型的高位32位为零,低阶32位等于整数参数的位。但是,我不明白这如何从方法体内部的代码中得出。在阅读该方法时,以下是我对正x的思路:当整数转换为 long 时,其符号位/最高有效位为零。因此,长整型符号位/最高有效位为零,低位等于整数的位。由于 long 具有所有最低阶 4 字节,并且由于只有这些字节中包含数据,因此此掩码不起作用,并且返回正确的结果。0xffffffff然而,当在负面的背景下阅读它时,我的理解就崩溃了:x当整数为 cst 到 long 时,其符号位/最高有效位为 1。因此,长号的符号位/最有效位是一,低阶位等于整数的位,除了第四个最低有效字节的最有效位是零,当它在整数中为1时。由于 long 在最低顺序为 4 个字节中具有所有 1,在最高顺序的 4 个字节中具有零,因此它具有更改长整型上的符号位的唯一效果,并使四个最低有效位中的错误整数保持不变。因此,它从此方法返回错误的答案,其中整数的符号位在移动到长整型时会更改。0xffffffff但是,当我测试此方法时,我得到的结果与Javadoc一致。我怀疑我误解了Java中按位运算符或其两个补码整数表示的一个或多个基本点,我希望这个问题可以澄清这些要点。
查看完整描述

1 回答

?
至尊宝的传说

TA贡献1789条经验 获得超10个赞

按位运算符的工作方式完全符合您的预期。它们是严格的位运算符,根本不考虑位的语义。


有时,使用断点运行代码最为简单。对于您的具体示例,我将操作的步骤转换为原子语句,并使用 打印结果。Long.toString


int x = -57;


// step 1:

long xCast = (long) x;

System.out.println(Long.toString(xCast, 2)); // -1110011 - this is not the bitwise representation however.


long mask = 0xffffffffL;

System.out.println(Long.toString(mask, 2)); // 11111111111111111111111111111111


// step 2:

long result = ((long) x) & mask;

System.out.println(Long.toString(result, 2)); // 11111111111111111111111111000111

步骤 1 是操作外观的主要原因。在 Java 中,所有(严格数字)值都是有符号的(字符是无符号的)。这意味着,正如您正确指出的那样,所有最高位都是符号位。然而,有趣的部分是,如果一个数字是负数,那么其余位会做什么。以下主题已经涵盖了“二的补码”的基础知识:什么是“2的补码”?这个维基百科页面也是如此:https://en.wikipedia.org/wiki/Two%27s_complement


为了缩短它,在java中,对于整数:


int zero = 0; // == 0b00000000_00000000_00000000_00000000


int maxPositive = Integer.MAX_VALUE; // == 0b01111111_11111111_11111111_11111111


int minus1 = -1; // == 0b11111111_11111111_11111111_11111111


int minNegative = Integer.MIN_VALUE; // == 0b10000000_00000000_00000000_00000000

因此,一切正常的原因是,如果整数为负数,则在强制转换时,整个上部 32 位将转换为 1,否则数字的表示值将发生变化。有效:


int x = 0b11111111_11111111_11111111_11000111;

转换为:


long xCast = 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11000111;

由于您作为开发人员希望该方法仅返回初始设置的位,因此您必须从结果中屏蔽上位。这是在步骤 2 中完成的。


因此,您的示例的答案:Java中非浮动值的表示是二的补码,因此,当智能地将值从int转换为long时,对于负数,上面的位被1填充。因此,它们必须被删除。


查看完整回答
反对 回复 2022-09-28
  • 1 回答
  • 0 关注
  • 198 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号