不理解Java 2';补语
我有以下代码:不理解Java 2';补语,java,int,twos-complement,Java,Int,Twos Complement,我有以下代码: 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 =
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.");
}
}
}
package.com公司;
导入java.net.InetAddress;
导入java.net.UnknownHostException;
公共班机{
私有最终静态int-broadcast=0xffffffff;//4294967295或255.255.255.255
私有最终静态int firstClassE=0xf0000000;//4026531840或240.0.0.0
公共静态int GetIntInetAddress(InetAddress到转换)
{
最后一个字节[]addr=toConvert.getAddress();
最终int ipAddr=
((addr[0]&0xFF)=firstClassE:true,curAddr=firstClassE:true,curAddr=firstClassE:false,curAddr=firstClassE:true,curAddr=firstClassE:true,curAddr=firstClassE:true,curAddr
我不理解的是,为什么数字和比较不是我期望的结果,但代码产生了我想要的结果。我想这是整个两个补码的事情,我只是因为某种原因没有“得到”。机械地说,我知道它(两个补码)是翻转位并加1,但我不明白的是,如果一些数字颠倒了,为什么我的比较工作正常
例如,在IP 1.0.0的第一次检查中,检查int值16777216是否小于255.255.255的int值,即-1。结果为假,但广播IP在转换为int时明显大于而不是小于1.0.0的IP。同样,1.0.0.0的检查至少为,或更高然后,240.0.0.0返回true,而我们知道情况显然不是这样
我已经检查了边界情况,一切都正常……我只是不明白为什么会这样(我编写了代码,所以请仔细想想!)。如果有一种更明确的方法来确定IP是否在某个范围内失效,我想探讨一下,因为我的方法一定没有意义,尽管有效(或者是否有效?)
在IntelliJ中,这种行为还有一个奇怪的例子。当我检查地址时,检查器会显示正确的值和负值,正如我在下图中用红色箭头突出显示的那样。使用Windows calc,我输入-84并转换为十六进制并收到FFF…FAC。当我输入172时,我只收到AC…为什么我要这样做得到相同的十六进制数,只是在most sig位置前加1
更新:
感谢所有耐心的讨论和精彩的回答!我想我已经了解了这件事的原理,但仍在努力解决使用的微妙之处。:)干杯!你是对的,这是一个二元补码的问题,我只能建议你仔细阅读并最终得到它-它会在各种整数溢出问题中一次又一次地困扰你(它甚至在一些核心Java库中使用) 问题本身是,在Java中,Integer包含从-(2^31)到(2^31)-1的数字。255*255*255*255的值是2^32-1。它不能表示为带符号的整数。因此,当您将IP转换为带符号的整数时,您不会得到(对您而言)合理的值值。如果要将IP与内置的“小于”进行比较,请在IP实际适合的位置使用原语,如
long
第二部分也发生了同样的事情。一个有符号的
字节
保存从-128到127的值。你把255放在那里。你为什么期望一个正常的结果呢?现在如果你在字节保存0..255的地方使用无符号算术,一切都很好。在32位2的补码中,非负整数是0x00000000
-0x7fffffff
并且这些以普通方式从十六进制转换为十进制
机器中的最低(即最负)数字表示为0x8000000
(即最高阶位,未设置其他位)。设置此位的真正含义是将31个低阶位指示的正整数添加到数字-(0x8000000)
练习:32位2的补码中的数字-84是什么?因为它是负数,我们必须设置高阶位。因此,我们从-(0x8000000)=-2147483648
开始。现在您可以用代数方法解出其他31位所需的值:
-2147483648 + x = -84
=> x = 2147483648 - 84
=> x = 2147483564
=> x = 0x7fffffac
很明显,如果你取0x8000000 | 0x7fffffac
,你会得到0xffffffac
显然,0x7fffffac=(0x7f000000+0xff0000+0xff00+0xac)
和括号中的表达式相当于(2130706432+16711680+65280+172)
。如果不考虑其他3个字节,低位字节相当于十进制172
,这一事实毫无意义
您的比较
现在您提到您的比较“不是您期望的结果”。我不知道您期望它们是什么,因为您没有解释,但我猜您希望IP地址的返回值在[240.0.0.0..255.255.255.255)
不包括范围的右侧。这意味着范围[0xf0000000..0xFFFFFF]中的IP地址不包括在内
如果这些是32位2的
-2147483648 + x = -84
=> x = 2147483648 - 84
=> x = 2147483564
=> x = 0x7fffffac
final long ipAddr =
(((long)addr[0] & 0xFF) << (3 * 8)) +
(((long)addr[1] & 0xFF) << (2 * 8)) +
(((long)addr[2] & 0xFF) << (1 * 8)) +
((long)addr[3] & 0xFF);
static int compareUnsigned(int x, int y) {
if (x >= 0 && y < 0) {
return -1; // y is actually greater than x if unsigned
}
else if (x < 0 && y >= 0) {
return 1; // x is greater than y if unsigned
} else {
return Integer.compare(x, y);
}
}
static int compareUnsigned(int x, int y) {
if (((x ^ y) & 0x80000000) != 0) { // see if x and y have different signs
return (x < 0) ? 1 : -1;
} else {
return Integer.compare(x, y);
}
}
static int compareUnsigned(int x, int y) {
return Integer.compare(x + Integer.MIN_VALUE, y + Integer.MIN_VALUE);
}
public static Boolean IsClassEAddress(InetAddress address)
{
int curAddr = GetIntInetAddress(address);
return ((curAddr & 0xF0000000) == 0xF0000000) && (curAddr != 0xFFFFFFFF);
}