[java] Finding absolute value of a number without using Math.abs()

Is there any way to find the absolute value of a number without using the Math.abs() method in java.

This question is related to java number-formatting absolute-value

The answer is


Use the class Math

Math.abs(num);

Although this shouldn't be a bottle neck as branching issues on modern processors isn't normally a problem, but in the case of integers you could go for a branch-less solution as outlined here: http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs.

(x + (x >> 31)) ^ (x >> 31);

This does fail in the obvious case of Integer.MIN_VALUE however, so this is a use at your own risk solution.


-num will equal to num for Integer.MIN_VALUE as

 Integer.MIN_VALUE =  Integer.MIN_VALUE * -1

In case of the absolute value of an integer x without using Math.abs(), conditions or bit-wise operations, below could be a possible solution in Java.

(int)(((long)x*x - 1)%(double)x + 1);

Because Java treats a%b as a - a/b * b, the sign of the result will be same as "a" no matter what sign of "b" is; (x*x-1)%x will equal abs(x)-1; type casting of "long" is to prevent overflow and double allows dividing by zero.

Again, x = Integer.MIN_VALUE will cause overflow due to subtracting 1.


You can use :

abs_num = (num < 0) ? -num : num;

Here is a one-line solution that will return the absolute value of a number:

abs_number = (num < 0) ? -num : num;

Like this:

if (number < 0) {
    number *= -1;
}

Since Java is a statically typed language, I would expect that a abs-method which takes an int returns an int, if it expects a float returns a float, for a Double, return a Double. Maybe it could return always the boxed or unboxed type for doubles and Doubles and so on.

So you need one method per type, but now you have a new problem: For byte, short, int, long the range for negative values is 1 bigger than for positive values.

So what should be returned for the method

byte abs (byte in) {
   // @todo
}

If the user calls abs on -128? You could always return the next bigger type so that the range is guaranteed to fit to all possible input values. This will lead to problems for long, where no normal bigger type exists, and make the user always cast the value down after testing - maybe a hassle.

The second option is to throw an arithmetic exception. This will prevent casting and checking the return type for situations where the input is known to be limited, such that X.MIN_VALUE can't happen. Think of MONTH, represented as int.

byte abs (byte in) throws ArithmeticException {
   if (in == Byte.MIN_VALUE) throw new ArithmeticException ("abs called on Byte.MIN_VALUE"); 
   return (in < 0) ? (byte) -in : in; 
}

The "let's ignore the rare cases of MIN_VALUE" habit is not an option. First make the code work - then make it fast. If the user needs a faster, but buggy solution, he should write it himself. The simplest solution that might work means: simple, but not too simple.

Since the code doesn't rely on state, the method can and should be made static. This allows for a quick test:

public static void main (String args []) {
    System.out.println (abs(new Byte ( "7")));
    System.out.println (abs(new Byte ("-7")));
    System.out.println (abs((byte)  7));
    System.out.println (abs((byte) -7));
    System.out.println (abs(new Byte ( "127")));
    try
    {
        System.out.println (abs(new Byte ("-128")));
    }
    catch (ArithmeticException ae)
    {
        System.out.println ("Integer: " + Math.abs (new Integer ("-128")));
    }
    System.out.println (abs((byte)  127));
    System.out.println (abs((byte) -128));
}

I catch the first exception and let it run into the second, just for demonstration.

There is a bad habit in programming, which is that programmers care much more for fast than for correct code. What a pity!


If you're curious why there is one more negative than positive value, I have a diagram for you.


Yes:

abs_number = (number < 0) ? -number : number;

For integers, this works fine (except for Integer.MIN_VALUE, whose absolute value cannot be represented as an int).

For floating-point numbers, things are more subtle. For example, this method -- and all other methods posted thus far -- won't handle the negative zero correctly.

To avoid having to deal with such subtleties yourself, my advice would be to stick to Math.abs().