Math.abs 返回 Integer.Min_VALUE 的错误值
此代码:
System.out.println(Math.abs(Integer.MIN_VALUE));
返回 -2147483648
它不应该返回绝对值 2147483648
吗?
This code:
System.out.println(Math.abs(Integer.MIN_VALUE));
Returns -2147483648
Should it not return the absolute value as 2147483648
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
Integer.MIN_VALUE
为-2147483648
,但 32 位整数可以包含的最大值为+2147483647
。尝试用 32 位 int 表示+2147483648
将有效地“翻转”为-2147483648
。这是因为,当使用有符号整数时,+2147483648
和-2147483648
的二进制补码表示形式是相同的。不过,这不是问题,因为+2147483648
被认为超出范围。要进一步阅读有关此问题的信息,您可能需要查看有关二进制补码的维基百科文章。
Integer.MIN_VALUE
is-2147483648
, but the highest value a 32 bit integer can contain is+2147483647
. Attempting to represent+2147483648
in a 32 bit int will effectively "roll over" to-2147483648
. This is because, when using signed integers, the two's complement binary representations of+2147483648
and-2147483648
are identical. This is not a problem, however, as+2147483648
is considered out of range.For a little more reading on this matter, you might want to check out the Wikipedia article on Two's complement.
你指出的行为确实是违反直觉的。但是,此行为是由
Math.abs(int)
的 javadoc:也就是说,
Math.abs(int)
的行为应类似于以下 Java 代码:即,在否定情况下为
-x
。根据 JLS 第 15.15 节。 4中,
-x
等于(~x)+1
,其中~
是按位求补运算符。为了检查这听起来是否正确,我们以 -1 为例。
整数值
-1
在 Java 中可以用十六进制表示为0xFFFFFFFF
(使用println
或任何其他方法检查)。因此,采用-(-1)
可以得到:所以,它有效。
现在让我们尝试一下
Integer.MIN_VALUE
。知道最低整数可以用0x80000000
表示,即第一位设置为 1,其余 31 位设置为 0,我们有:这就是为什么
Math.abs( Integer.MIN_VALUE)
返回Integer.MIN_VALUE
。另请注意,0x7FFFFFFF
是Integer.MAX_VALUE
。那么,我们如何避免未来由于这种反直觉的返回值而出现问题呢?
我们可以,正如指出的那样@Bombe,将我们的
int
转换为long
。然而,我们必须要么Integer.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE)
。long
,希望我们永远不会使用等于Long.MIN_VALUE
的值调用Math.abs(long)
>,因为我们还有Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE
。我们可以在任何地方使用 BigInteger,因为
BigInteger.abs()
确实总是返回正值。这是一个很好的替代方案,尽管比操作原始整数类型慢一点。我们可以为
Math.abs(int)
编写自己的包装器,如下所示:Integer.MAX_VALUE
溢出到0
,而不是Integer.MIN_VALUE
)最后要注意的是,此问题似乎认识有一段时间了。例如,请参阅有关相应 findbugs 规则的此条目。
The behaviour you point out is indeed, counter-intuitive. However, this behaviour is the one specified by the javadoc for
Math.abs(int)
:That is,
Math.abs(int)
should behave like the following Java code:That is, in the negative case,
-x
.According to the JLS section 15.15.4, the
-x
is equal to(~x)+1
, where~
is the bitwise complement operator.To check whether this sounds right, let's take -1 as example.
The integer value
-1
is can be noted as0xFFFFFFFF
in hexadecimal in Java (check this out with aprintln
or any other method). Taking-(-1)
thus gives:So, it works.
Let us try now with
Integer.MIN_VALUE
. Knowing that the lowest integer can be represented by0x80000000
, that is, the first bit set to 1 and the 31 remaining bits set to 0, we have:And this is why
Math.abs(Integer.MIN_VALUE)
returnsInteger.MIN_VALUE
. Also note that0x7FFFFFFF
isInteger.MAX_VALUE
.That said, how can we avoid problems due to this counter-intuitive return value in the future?
We could, as pointed out by @Bombe, cast our
int
s tolong
before. We, however, must eitherint
s, which does not work becauseInteger.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE)
.long
s somehow hoping that we'll never callMath.abs(long)
with a value equal toLong.MIN_VALUE
, since we also haveMath.abs(Long.MIN_VALUE) == Long.MIN_VALUE
.We can use
BigInteger
s everywhere, becauseBigInteger.abs()
does indeed always return a positive value. This is a good alternative, though a bit slower than manipulating raw integer types.We can write our own wrapper for
Math.abs(int)
, like this:int positive = value & Integer.MAX_VALUE
(essentially overflowing fromInteger.MAX_VALUE
to0
instead ofInteger.MIN_VALUE
)As a final note, this problem seems to be known for some time. See for example this entry about the corresponding findbugs rule.
以下是 Java 文档在 javadoc:
Here is what Java doc says for Math.abs() in javadoc:
要查看您期望的结果,请将
Integer.MIN_VALUE
转换为long
:To see the result that you are expecting, cast
Integer.MIN_VALUE
tolong
:Java 15 中对此进行了修复,将使用 int 和 long 方法。它们将出现在类
方法中。
如果您通过
或
抛出异常。
https://bugs.openjdk.java.net/browse/JDK-8241805
我想看看 Long.MIN_VALUE 或 Integer.MIN_VALUE 是否传递正值将返回而不是异常。
There is a fix to this in Java 15 will be a method to int and long. They will be present on the classes
The methods.
If you pass
OR
A Exception is thrown.
https://bugs.openjdk.java.net/browse/JDK-8241805
I would like to see if either Long.MIN_VALUE or Integer.MIN_VALUE is passed a positive value would be return and not a exception but.
2147483648在java中不能存储为整数,其二进制表示形式与-2147483648相同。
2147483648 cannot be stored in an integer in java, its binary representation is the same as -2147483648.
但是
(int) 2147483648L == -2147483648
有一个负数没有正数等价物,因此它没有正值。您将在 Long.MAX_VALUE 中看到相同的行为。But
(int) 2147483648L == -2147483648
There is one negative number which has no positive equivalent so there is not positive value for it. You will see the same behaviour with Long.MAX_VALUE.Math.abs 并不总是适用于大数字,我使用我 7 岁时学到的这个小代码逻辑!
Math.abs doesn't work all the time with big numbers I use this little code logic that I learnt when I was 7 years old!