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.
Answer from jonmorgan on Stack OverflowWhich Java method is used to find the absolute value of a number? Question 9Select one: a. Math.abs() b. Math.sqrt()...
java - Math.abs returns wrong value for Integer.Min_VALUE - Stack Overflow
Should I be using Math.abs?
import - java.lang.Math.abs not imported by default? - Stack Overflow
Videos
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.
The behaviour you point out is indeed, counter-intuitive. However, this behaviour is the one specified by the javadoc for Math.abs(int):
If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.
That is, Math.abs(int) should behave like the following Java code:
public static int abs(int x){
if (x >= 0) {
return x;
}
return -x;
}
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 as 0xFFFFFFFF in hexadecimal in Java (check this out with a println or any other method). Taking -(-1) thus gives:
-(-1) = (~(0xFFFFFFFF)) + 1 = 0x00000000 + 1 = 0x00000001 = 1
So, it works.
Let us try now with Integer.MIN_VALUE . Knowing that the lowest integer can be represented by 0x80000000, that is, the first bit set to 1 and the 31 remaining bits set to 0, we have:
-(Integer.MIN_VALUE) = (~(0x80000000)) + 1 = 0x7FFFFFFF + 1
= 0x80000000 = Integer.MIN_VALUE
And this is why Math.abs(Integer.MIN_VALUE) returns Integer.MIN_VALUE. Also note that 0x7FFFFFFF is Integer.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
ints tolongbefore. We, however, must either- cast them back into
ints, which does not work becauseInteger.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE). - Or continue with
longs 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.
- cast them back into
We can use
BigIntegers 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:
/**
* Fail-fast wrapper for {@link Math#abs(int)}
* @param x
* @return the absolute value of x
* @throws ArithmeticException when a negative value would have been returned by {@link Math#abs(int)}
*/
public static int abs(int x) throws ArithmeticException {
if (x == Integer.MIN_VALUE) {
// fail instead of returning Integer.MAX_VALUE
// to prevent the occurrence of incorrect results in later computations
throw new ArithmeticException("Math.abs(Integer.MIN_VALUE)");
}
return Math.abs(x);
}
- Use a integer bitwise AND to clear the high bit, ensuring that the result is non-negative:
int positive = value & Integer.MAX_VALUE(essentially overflowing fromInteger.MAX_VALUEto0instead 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.
I'm trying to test to see if a number is between 18-24 Im working through programmingbydoing.com Lesson 25.
import java.util.Scanner;
public class HowOldAreYou2 { public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); String name; int age;
System.out.print("What your name?");
name = keyboard.next();
System.out.print(name + ", how old are you?");
age = keyboard.nextInt();
if (age < 16)
{
System.out.print("You cant drive");
}
else if (age == 16 | age == 17)
{
System.out.print("You can drive but you can't vote");
}
else if (age == Math.abs(18-24))
{
System.out.print("You can vote but not rent a car");
}
}}
But my question is if java.lang.* is imported by default then why is the Math class not imported and the abs method not available?
Because it isn't.
Because that is the way that Java works. An implicit (or explicit) wildcard import of the classes in a package only imports the classes. It doesn't also do a static import of class members.
If you want to refer to all static members of a class without qualifying them, you should use a wildcard static import; e.g.
import static java.lang.Math.*;
Alternatively you can static import individual members; e.g.
import static java.lang.Math.abs;
Why did they define Java this way?
Well it is most likely rationale is that implicit importing makes it harder to read code. If methods like abs get imported by default, then you need to know what they all are ... and where they are imported from ... in order to understand the true meaning of the code.
It is worth knowing that static imports were only added in Java 5. Prior to that, it was not possible to refer to Math.abs without the Math qualification.
If you just import the class not its static members then what are you getting when you import it?
You just get the class name. For example:
import java.util.HashMap;
allows me to write new HashMap() rather than new java.util.HashMap() etcetera. This is significant. (Imagine if you always had to refer to classes by their full name ....)
you have to call abs() method on class name of math class Math.abs(), It is static method.
or you have to import import static java.lang.Math.abs;
Internal Implementation of Math class absolute() method.
public static long abs(long a) {
return (a < 0) ? -a : a;
}
abs() method is static method, java.lang.*; can not import static member of class.