我有以下if情况。
if (i == -i && i != 0)
在Java中,此条件i将返回什么值true?
我无法想到在Java 中i考虑二进制补码表示法的任何这种价值。
我也想对这种情况的答案有代数证明(在Java中)?
-0.0也是== 0
if(i && i == -i)
我有以下if情况。
if (i == -i && i != 0)
在Java中,此条件i将返回什么值true?
我无法想到在Java 中i考虑二进制补码表示法的任何这种价值。
我也想对这种情况的答案有代数证明(在Java中)?
-0.0也是== 0
if(i && i == -i)
Answers:
int它起作用的唯一值是 Integer.MIN_VALUE。
这是因为整数使用二进制补码求反。
使用
System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));
你看那Integer.MIN_VALUE是
10000000000000000000000000000000
取负值的方法是先交换0和1,然后得出
01111111111111111111111111111111
并通过添加1,
10000000000000000000000000000000
正如您在我给的链接中看到的那样,Wikipedia提到了负数最多的问题,并指出这是唯一的例外:
二进制补数中最负的数字有时称为“怪异数字”,因为它是唯一的例外。
当然,Long.Min_Value如果将其存储在long变量中,也会有相同的现象。
请注意,这仅是由于在Java中对ints的二进制存储所做的选择。另一个(错误的)解决方案例如可以通过简单地更改最高有效位并使其他位保持不变来求反,这样可以避免MIN_VALUE出现此问题,但是会产生2个不同的0值和复杂的二进制算术(您将如何例如增加?)。
您正在寻找的价值是Integer.MIN_VALUE。
我也很想得到这个条件有什么答案的代数证明(在Java中)?
对于Stack Exchange而言,这是不合时宜的。但是您可以从Java整数(JLS 4.2)的定义开始
“整数类型为byte,short,int和long,它们的值是8位,16位,32位和64位带符号的二进制补码整数……”
和
“整数类型的值是以下范围内的整数...对于int,从-2147483648到2147483647(含)之间”
以及Java一元'-'运算符的定义(JLS 15.15.4):
“对于整数值,取反等于从零减去。Java编程语言对整数使用二进制补码表示形式,并且二进制补码值的范围不是对称的,因此对最大负整数或长整数取负会导致整数取反。相同的最大负数。在这种情况下会发生溢出,但不会引发异常。对于所有整数x,-x等于(〜x)+1。”
i != -i)。剩下两个数字:0和Integer.MIN_VALUE。因为i != 0在您的情况下,仅MIN_VALUE剩下。
除了到目前为止给出的答案之外...
共有四个值
int i = Integer.MIN_VALUE;
long i = Long.MIN_VALUE;
Integer i = Integer.valueOf(Integer.MIN_VALUE);
Long i = Long.valueOf(Long.MIN_VALUE);
包装的值将被解包,因此此表达式也适用。
注意:Math.abs文档。
公共静态int abs(int a)
返回int值的绝对值。如果参数不是负数,则返回参数。如果参数为负,则返回参数取反。
请注意,如果参数等于Integer.MIN_VALUE的值(最负的可表示int值),则结果是相同的值,该值为负。
和
公共静态长ABS(长A)
返回一个long值的绝对值。如果参数不是负数,则返回参数。如果参数为负,则返回参数取反。
请注意,如果参数等于Long.MIN_VALUE的值(最负的可表示长值),则结果是相同的值,该值为负。
令人惊讶的是Math.abs可能返回负数。这可能是由于a)在这些情况下-MIN_VALUE没有正值b)执行-计算导致溢出。
同样令人感兴趣的是为什么Byte.MIN_VALUE,Short.MIN_VALUE不这样做。这是因为将-这些类型更改int为,因此不会溢出。
Character.MIN_VALUE没问题,因为它是0。
Float.MIN_VALUE和Double.MIN_VALUE具有不同的含义。这些是大于零的最小可表示值。因此,它们具有不是它们自己的有效负值。
就像其他人提到的那样,这只能通过实现Integer.MIN_VALUE。至于证明,除了二进制以外,让我提供一个更容易理解的解释(尽管它仍然植根于该解释中)。
需要注意的是Integer.MIN_VALUE等于-2^31或-2147483648和Integer.MAX_VALUE等于2^31-1或2147483647。-Integer.MIN_VALUE是2^31,现在对于Integer而言太大(因为它过去了MAX_VALUE),从而导致Integer溢出,Integer.MIN_VALUE再次出现。这是唯一执行此操作的Integer,因为MIN_VALUE它是唯一一个除了0以外都没有负等价的数字。
2147483648可能仅在以下情况下出现在源代码中:作为一元减运算符(JLS 3.10.1)的操作数。
初步的代数证明,使用modulo 2^32算术:
i == -i可以改写为2 * i == 0(i两面都加),或i << 1 == 0。
该方程式具有两个形式的解i == 0 >> 1,即0b和10000000000000000000000000000000b通过向左0或1向左移动而获得。
解决方案i == 0被排除在外,剩下的就是解决方案i == 100000000000000000000000000000000b。
也许它不是太有教育意义,但与其认为可以运行以下代码,不如说:
for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
{
if (i == -i && i != 0)
{
System.out.println(i);
}
}
看到它打印
-2147483648
-2147483648
无限地 :)
<