The absolute value is the distance from the origin of a number at its corresponding point on the number line, so in mathematics, the absolute value of a positive number is the number itself, and the absolute value of a negative number should be its negative.
Almost everyone knows this.
In Java, to get the absolute value of a number, use the abs method in java.lang.Math. There are four overloaded ABS methods:
public static int abs(int a) { return (a < 0) ? -a : a; } public static long abs(long a) { return (a < 0) ? -a : a; } public static float abs(float a) {return (float a <= 0.0f)? 0.0f -a: a; 0.0f -a: a; } public static double abs(double a) {return (a <= 0.0d)? 0.0D - a: a; }Copy the code
Returns the absolute value of int, long, float, and double, respectively. The logic in these methods is simple.
So, based on all of this, we often use math. abs directly to take the absolute value of a number.
There are many examples of this in our code.
For example, we need to use the order number for the sub-table, but the order number is a string, so we need to get the hashCode of this character, because hashCode can be negative, and then take the absolute value of hashCode, and use this value to modulus the sub-table number:
Math.abs(orderId.hashCode()) % 1024;
Copy the code
However, the above logic is flawed!!
Because in a very special case, the above code will produce a negative value.
The very special case is when hashCode is integer.min_value, which is the smallest value that an Integer can represent.
public static void main(String[] args) {
System.out.println(Math.abs(Integer.MIN_VALUE));
}
Copy the code
Executing the above code yields the following:
- 2147483648.Copy the code
Obviously, this is a negative number!!
Why is that?
The value range of int is -2^31 — (2^31) -1, which is -2147483648 to 2147483647
So, when we use abs to take the absolute value, and we want to get the absolute value of -2147483648, that should be 2147483648.
However, 2147483648 is greater than 2147483647, which is outside the range of int. That’s when a boundary crossing happens.
2147483647 is expressed in binary complement:
01111111 11111111 11111111 11111111
This number +1 gives:
10000000 00000000 00000000 00000000
This binary is the complement of -2147483648.
Although, the probability of this happening is very low, only if the absolute value of the number you’re taking is -2147483648, you’re still getting a negative number.
So how to solve this problem?
So if you think you’re crossing the line and you’re going to end up with a negative number, you’re going to solve the crossing problem, which is before you take the absolute value, you’re going to convert this int to a long, so you don’t cross the line.
For example, our previous sub-table logic is changed to
Math.abs((long)orderId.hashCode()) % 1024;
Copy the code
You’re safe.
You can execute the following code:
public static void main(String[] args) {
System.out.println(Math.abs((long)Integer.MIN_VALUE));
}
Copy the code
The result is:
2147483648
Copy the code
Above, is today to introduce the knowledge point.
Remember, however, that this can happen when you take the absolute value of a long. It just happens less often, but as long as it exists, it can happen!
About the author: Hollis, a person with a unique pursuit of Coding, is an Alibaba technologist, the co-author of three Courses for Programmers, and the author of a series of articles on how Java Engineers Become Gods.
Follow the public account [Hollis], reply “God map” in the background, you can get Java engineer advanced mind map.