Home » Java » java – distanceTo() integer overflow?-Exceptionshub

java – distanceTo() integer overflow?-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

This is my method to determine the distance between two points:


    // Euclidean distance between this point and that point
    public int distanceTo(Point that) {
        int distanceX = this.x - that.x;
        int distanceY = this.y - that.y;
        return (int) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
    }

Is it possible that an integer overflow occurs, and if so, how can I prevent it?

EDIT:

enter image description here

How to&Answers:

To prevent incorrect result from overflow, use the Math “exact” methods:

1) Or the long variant.

The methods will throw an ArithmeticException if overflow would have occurred.

public int distanceTo(Point that) throws ArithmeticException {
    int distanceX = Math.subtractExact(this.x, that.x);
    int distanceY = Math.subtractExact(this.y, that.y);
    return (int) Math.sqrt(Math.addExact(Math.multiplyExact(distanceX, distanceX),
                                         Math.multiplyExact(distanceY, distanceY)));
}

Of course it might be prudent to use long math to minimize the probability of overflow.

public int distanceTo(Point that) {
    long distanceX = Math.subtractExact((long) this.x, (long) that.x);
    long distanceY = Math.subtractExact((long) this.y, (long) that.y);
    long sumOfSquares = Math.addExact(Math.multiplyExact(distanceX, distanceX),
                                      Math.multiplyExact(distanceY, distanceY));
    return Math.toIntExact((long) Math.sqrt(sumOfSquares));
}

There might be a small loss of precision when sumOfSquares is widened to a double, but the effect would likely be lost when decimals are discarded during cast to long.

Answer:

First you can use the hypotenuse function.

Then integer overflow may happen at a distance (-).

The solution is to use double, as the the final result is calculated using a floating point function.

The result could be as large as sqrt(2)*2*Integer.MAX_VALUE, also overflowing.

So:

public int distanceTo(Point that) {
    double distanceX = ((double)this.x) - that.x;
    double distanceY = ((double)this.y) - that.y;
    double distance = Math.hypot(distanceX, distanceY);
    if (distance + 1 >= Integer.MAX_VALUE) {
        throw new ArithmeticException("Integer overflow");
    }
    return (int) distance; // (int) Math.round?
}

Or neater (as did Andreas):

public int distanceTo(Point that) {
    double distanceX = ((double)this.x) - that.x;
    double distanceY = ((double)this.y) - that.y;
    double distance = Math.hypot(distanceX, distanceY);
    return Math.toIntExact((long)distance); // (int) Math.round?
}

Answer:

You can define a method to check the int overflow. A quick demo is as follows:

class Main {
    public static void main(String[] args) {
        // Test
        int x = 0;
        System.out.println("Square of " + x + " overflows int: " + isIntOverflowForSquare(x));
        x = 123;
        System.out.println("Square of " + x + " overflows int: " + isIntOverflowForSquare(x));
        x = 1234567890;
        System.out.println("Square of " + x + " overflows int: " + isIntOverflowForSquare(x));
        x = Integer.MAX_VALUE;
        System.out.println("Square of " + x + " overflows int: " + isIntOverflowForSquare(x));
    }

    static boolean isIntOverflowForSquare(int x) {
        if (x == 0)
            return false;

        int square = x * x;
        if (x == square / x)
            return false;
        else
            return true;
    }
}

Output:

Square of 0 overflows int: false
Square of 123 overflows int: false
Square of 1234567890 overflows int: true
Square of 2147483647 overflows int: true