gpt4 book ai didi

java - 看不懂 Java 补码

转载 作者:行者123 更新时间:2023-12-04 22:01:04 28 4
gpt4 key购买 nike

我有这个代码:

package com.company;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class Main {

private final static int broadcast = 0xffffffff; //4294967295, or 255.255.255.255
private final static int firstClassE = 0xf0000000; //4026531840, or 240.0.0.0

public static int GetIntInetAddress(InetAddress toConvert)
{
final byte[] addr = toConvert.getAddress();

final int ipAddr =
((addr[0] & 0xFF) << (3 * 8)) +
((addr[1] & 0xFF) << (2 * 8)) +
((addr[2] & 0xFF) << (1 * 8)) +
(addr[3] & 0xFF);

return ipAddr;
}

public static Boolean IsClassEAddress(InetAddress address)
{
int curAddr = GetIntInetAddress(address);
Boolean test1 = curAddr >= firstClassE;
Boolean test2 = curAddr < broadcast;
System.out.println(String.format("\ncurAddr: %s, firstClassE: 240.0.0.0, broadcast: 255.255.255.255", address.getHostAddress()));
System.out.println(String.format("curAddr: %d, firstClassE: %d, broadcast: %d, curAddr >= firstClassE: %s, curAddr < broadcast: %s",
curAddr, firstClassE, broadcast, test1 ? "true" : "false", test2 ? "true" : "false"));
return (test1 && test2) ? true : false;
}

public static void main(String[] args) throws UnknownHostException
{
if (IsClassEAddress(InetAddress.getByName("1.0.0.0")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
if (IsClassEAddress(InetAddress.getByName("250.0.0.0")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
if (IsClassEAddress(InetAddress.getByName("239.255.255.255")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
if (IsClassEAddress(InetAddress.getByName("240.0.0.0")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
if (IsClassEAddress(InetAddress.getByName("240.0.0.1")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
if (IsClassEAddress(InetAddress.getByName("255.255.255.255")))
{
// Raise a flag
System.out.println("Class E IP address detected.");
}
}
}

产生以下输出:

curAddr: 1.0.0.0, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: 16777216, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: true, curAddr < broadcast: false

curAddr: 250.0.0.0, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: -100663296, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: true, curAddr < broadcast: true
Class E IP address detected.

curAddr: 239.255.255.255, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: -268435457, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: false, curAddr < broadcast: true

curAddr: 240.0.0.0, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: -268435456, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: true, curAddr < broadcast: true
Class E IP address detected.

curAddr: 240.0.0.1, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: -268435455, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: true, curAddr < broadcast: true
Class E IP address detected.

curAddr: 255.255.255.255, firstClassE: 240.0.0.0, broadcast: 255.255.255.255
curAddr: -1, firstClassE: -268435456, broadcast: -1, curAddr >= firstClassE: true, curAddr < broadcast: false

我不明白的是为什么数字和比较不是我期望的那样,但代码却产生了我想要的结果。我收集到它是整个补码的东西,出于某种原因我只是不“明白”。从机械上讲,我知道它(二进制补码)是翻转位并加 1,但我不明白的是,如果某些数字被反转,为什么我的比较工作正常?

例如,在第一次检查 IP 1.0.0.0 时,检查 int 值 16777216 是否小于 255.255.255.255 的 int 值,即 -1。结果是false,但是广播IP转换成int后明显比1.0.0.0的IP大,而不是小。同样,检查 1.0.0.0 是否至少或高于 240.0.0.0 会返回 true,而我们知道这显然不是这种情况。

我已经检查了边界情况并且一切正常......我只是不明白为什么会这样(我写了代码,所以去看看吧!)。如果有更明确的方法来确定 IP 是否在某个范围内,我想探索一下,因为我的方法一定没有意义,尽管工作(或者这样做?)

在 IntelliJ 中,还有此行为的另一个奇怪示例。当我检查一个地址时,检查器同时显示了正确的值和负值,正如我在下图中用红色箭头突出显示的那样。使用 Windows calc,我输入 -84 并转换为十六进制并收到 FFF...FAC。当我输入 172 时,我只收到 AC...为什么我得到相同的十六进制数,只是在最重要的位置前面有一个 1?

Another strange example I've seen

更新:

感谢所有耐心的讨论和出色的回答!我想我明白了这件事的机制,但仍在努力应对使用的微妙之处。 :) 干杯!

最佳答案

在 32 位二进制补码中,非负整数是 0x00000000 - 0x7fffffff 并且这些整数以普通方式从十六进制转换为十进制。

最低(最负)数在机器中表示为0x80000000(最高位,没有其他位已设置)。设置此位的真正含义是将 31 个低位位指示的正整数添加到数字 -(0x80000000) 中。

练习:32 位二进制补码中的-84 是多少? 因为它是负数,所以我们必须设置高位。所以我们从 -(0x80000000) = -2147483648 开始。现在您可以用代数方法解决其他 31 位需要的内容:

-2147483648 + x = -84
=> x = 2147483648 - 84
=> x = 2147483564
=> x = 0x7fffffac

很明显,如果您使用 0x80000000 | 0x7fffffac ,您将获得 0xffffffac

显然 0x7fffffac = (0x7f000000 + 0xff0000 + 0xff00 + 0xac) 和括号中的表达式等同于 (2130706432 + 16711680 + 65280 + 172) 。如果不考虑其他3个字节,低位字节相当于十进制172是没有意义的。

您的比较

现在您提到您的比较“不是您期望的那样”。我不知道你期望它们是什么,因为你还没有解释,但我的猜测是你想要一个 true 范围右侧 [240.0.0.0 .. 255.255.255.255) 不包含范围内的 IP 地址的 [0xf0000000 .. 0xffffffff) 返回值。这意味着 [-268435456, -1) 非包含范围内的 IP 地址。

如果这些是 32 位二进制补码整数,则这是 (0xf0000000 <= ip_addr && ip_addr < 0xffffffff) 范围,因此 boolean 形式的任何表达式都会给您正确的结果。

由于您的函数返回上述表达式的更复杂版本,因此它给出了正确的结果。

对了,你熟悉Boolean类型吗?您的方法是否出于某种原因需要返回装箱原语( ojit_code)?

关于java - 看不懂 Java 补码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24289647/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com