【发布时间】:2014-06-18 15:34:50
【问题描述】:
我有这个代码:
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。结果是假的,但是广播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...为什么我得到相同的十六进制数字,只是在最 sig 位置前面有一个 1?
更新:
感谢所有耐心的讨论和出色的答案!我想我了解了事物的机制,但仍在努力解决使用的微妙之处。 :) 干杯!
【问题讨论】:
-
那是一大堵代码和输出。你能不能提供一个小小的 sn-p 来证明你对二进制补码的误解?
-
"广播 IP,当转换为 int 时,显然比 1.0.0.0 的 IP 更大,而不是更小" -- 这一点都不“明显”。二进制中的
1.0.0.0是0x01000000,255.255.255.255是0xFFFFFFFF。第一个值代表16777216,第二个值代表-1。你不能通过说你没有“得到”二进制补码来改变这一点。就是这样。 -
如果你想让比较正常工作,最简单的方法是使用
long而不是int,然后一切都会是肯定的。 -
return (test1 && test2) ? true : false;trololo -
0xFFFFFFFF比0x01000000“大”仅当比较无符号时。作为已签名的Javaint,它更小。
标签: java int twos-complement