我试图在Java中使用128位BigInteger进行逐位执行。我有一个128位的数字,其前64位设置为1,最后64位设置为0(我正在使用IPv6掩码)。
BigInteger b = new BigInteger(2).pow(64).subtract(BigInteger.ONE).shiftLeft(64);
System.out.println(b.toString(2));
如果我使用base 2输出它,则会产生以下结果:
11111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000
我试图使用按位来翻转/反转所有位。
System.out.println(b.not().toString(2));
根据我的理解而不是,我希望所有的1都改为0,所有的0都改为1,但我得到以下内容:
-11111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000
这似乎也符合not()
函数的文档:
当且仅当此BigInteger为非负
时,此方法才返回负值
这是循环所有128位而不是逐位执行按位的情况吗?
更新的 如果我试着解释一下我想要实现的目的,那么它可能会有所帮助。我正在操纵IPv6地址,并试图根据IPv6掩码确定给定的IPv6地址是否在子网内。
根据回复,我认为以下内容应该有效:
E.g。 是2001:db8:0:0:8:800:200c:417b在2001年:db8 :: / 64?
BigInteger n = new BigInteger(1, InetAddress.getByName("2001:db8::").getAddress());
BigInteger b = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE).shiftLeft(64);
// First Address in Subnet
BigInteger first = n.and(b);
// Last Address in Subnet (this is where I was having a problem as it was returning a negative number)
BigInteger MASK_128 = BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE);
BigInteger last = first.add(b.xor(MASK_128));
// Convert our test IP into BigInteger
BigInteger ip = new BigInteger(1, InetAddress.getByName("2001:db8:0:0:8:800:200c:417b").getAddress());
// Check if IP is >= first and <= last
if ((first.compareTo(ip) <= 0) && (last.compareTo(ip) >= 0)) {
// in subnet
}
答案 0 :(得分:2)
正如其他人所指出的那样,它的标志位会给你一些你不想要的结果。
有两种方法可以获得反转位。对于它们两者,您将需要128位掩码值:
private static final BigInteger MASK_128 =
BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE);
然后你可以屏蔽符号位:
BigInteger b = BigInteger.valueOf(2).pow(64).subtract(BigInteger.ONE).shiftLeft(64);
System.out.println(MASK_128.andNot(b).toString(2));
或使用xor直接反转:
System.out.println(b.xor(MASK_128).toString(2));
我希望一旦你开始充实东西,掩码值在其他地方也会有用。
答案 1 :(得分:1)
有符号字节64 = 01000000
反转
我们得到签名字节-65 = 10111111
签署&#34;减去&#34;是&#34;不是&#34;运营商本身:
-1000000 = 0111111
键入此内容,您会看到绝对值
中的值相等(+1)System.out.println(b.toString());
System.out.println(b.not().toString());
答案 2 :(得分:1)
你的回答是完全正确的,在java中,所有内容都是恭维:
将十进制转换为二的补码
将数字转换为二进制(暂时忽略该符号),例如5是0101,-5是0101
如果数字是正数,那么你就完成了。例如5是使用二进制补码表示法的二进制0101。
以下是您的解决方案。
If the number is negative then
3.1 find the complement (invert 0's and 1's) e.g. -5 is 0101 so finding the complement is 1010
3.2 Add 1 to the complement 1010 + 1 = 1011. Therefore, -5 in two's complement is 1011.
那么,如果你想在二进制文件中做2 +( - 3)怎么办? 2 +( - 3)为-1。如果您使用符号幅度来添加这些数字,您需要做什么? 0010 + 1101 =?
使用二进制补码考虑它是多么容易。
2 = 0010
-3 = 1101
+
-1 = 1111
将两个补码转换为十进制
将1111转换为十进制:
数字以1开头,所以它是负数,所以我们找到了1111的补码,即0000。
添加1到0000,我们获得0001。
将0001转换为十进制,即1。
应用sign = -1。
在你的情况下
当你b.not().toString(2)
时,你会收到回复:
-11111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000001
最后一位 1 。
现在做两个人的恭维,你会得到正确的答案。
e.g;将所有 1 翻转为 0 ,反之亦然。在这之后添加一个解决方案,你将得到你正在寻求的解决方案。
最终解决方案
00000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
答案 3 :(得分:0)
使用
VALUE = 0xFFFFFFFFFFFFFFFF0000000000000000 - 这是第1位... 10 ... 0
的模式VALUE = 0x0000000000000000FFFFFFFFFFFFFFFF - 这是第0位... 01 ... 1
的模式只需手动输入16 x“F”和“0”,并记住在每个模式之前添加“0x”。 将此值定义为最终值。
如果你想生成这样的值,你必须这样做 值+ = 0x1; 值&lt;&lt; 1; n次。在你的情况下,n是64。