Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java distanceTo()整数溢出?_Java_Integer_Integer Overflow - Fatal编程技术网

Java distanceTo()整数溢出?

Java distanceTo()整数溢出?,java,integer,integer-overflow,Java,Integer,Integer Overflow,这是我确定两点之间距离的方法: // 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 * distance

这是我确定两点之间距离的方法:


    // 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);
    }

是否可能发生整数溢出,如果是,如何防止

编辑:

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

为了防止错误结果溢出,请使用
数学方法
“精确”方法:

  • 一,
  • 一,
  • 一,
  • 一,
  • 一,
  • 一,
1) 或
long
变体

如果发生溢出,这些方法将抛出一个
算术异常

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)));
}
当然,使用
long
math来最小化溢出的可能性可能是谨慎的

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));
}

sumOfSquares
扩大到
double
时,可能会有一点精度损失,但如果在转换为
long
期间丢弃小数,则可能会失去效果。为防止错误结果溢出,请使用
数学
精确方法:

  • 一,
  • 一,
  • 一,
  • 一,
  • 一,
  • 一,
1) 或
long
变体

如果发生溢出,这些方法将抛出一个
算术异常

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)));
}
当然,使用
long
math来最小化溢出的可能性可能是谨慎的

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));
}
sumOfSquares
扩大到
double
时,可能会有一点精度损失,但如果在转换为
long
时丢弃小数,则可能会失去效果。首先,您可以使用该函数

然后,整数溢出可能会在一定距离(
-
)发生

解决方案是使用double,因为最终结果是使用浮点函数计算的

结果可能大到
sqrt(2)*2*Integer.MAX_值
,也会溢出

因此:

或者更整洁(安德烈亚斯也是):

首先,您可以使用该函数

然后,整数溢出可能会在一定距离(
-
)发生

解决方案是使用double,因为最终结果是使用浮点函数计算的

结果可能大到
sqrt(2)*2*Integer.MAX_值
,也会溢出

因此:

或者更整洁(安德烈亚斯也是):


您可以定义一个方法来检查
int
溢出。下面是一个快速演示:

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;
    }
}
输出:

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

您可以定义一个方法来检查
int
溢出。下面是一个快速演示:

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;
    }
}
输出:

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


答案取决于x和y使用的坐标。如果保证它们足够小,就不会有整数溢出的风险。它们也是整数,但仍然可能溢出,对吗?如果平方根大于
integer.MAX\u VALUE
,则它们似乎代表二维坐标。两个x(或y)坐标之间的差值是否可以大于
整数。最大值
?如果答案为真,那么您的方法应该执行long减法,并返回long。(x,y)是x和y都是32位整数的点。两点之间的距离可以大于2^{31}-1。如果距离不是有效的32位整数,如何引发异常?答案取决于您使用的x和y坐标。如果保证它们足够小,就不会有整数溢出的风险。它们也是整数,但仍然可能溢出,对吗?如果平方根大于
integer.MAX\u VALUE
,则它们似乎代表二维坐标。两个x(或y)坐标之间的差值是否可以大于
整数。最大值
?如果答案为真,那么您的方法应该执行long减法,并返回long。(x,y)是x和y都是32位整数的点。两点之间的距离可以大于2^{31}-1。如果距离不是有效的32位整数,如何引发异常?谢谢。你的第二种方法比安德烈亚斯的短。它仍然以完全相同的方式工作吗?让投票保持原样-差别很小,我的答案是稍后。使用hypot,我的解决方案在x&y距离上没有溢出。x dist 2*MAX,y dist MAX/2/sqrt(2)适用于我的答案。当然,使用斜边有助于提升自尊。谢谢。你的第二种方法比安德烈亚斯的短。它仍然以完全相同的方式工作吗?让投票保持原样-差别很小,我的答案是稍后。使用hypot,我的解决方案在x&y距离上没有溢出。x dist 2*MAX,y dist MAX/2/sqrt(2)适用于我的答案。当然,使用斜边有助于提升自尊。谢谢!这就成功了。(但是,对
distanceX
distanceY
的强制转换是多余的,因为会发生加宽转换)@LudwigvonDrake如果不强制转换其中至少一个,它将调用
int subtractExact(int x,int y)
重载并加宽结果,而不是
long subtractExact(long x,long y)
它在减法之前变宽,可以处理例如
Integer.MAX\u值-Integer.MIN\u值
而不会导致溢出。@LudwigvonDrake您错了。当参数为
int
时,调用
int
版本,然后将结果扩大到
long
。@LudwigvonDrake两次强制转换中的1次是多余的。@LudwigvonDrake这完全由您决定。这对打电话的人来说是否重要,即打电话的人是否想抓住它。我猜不是,所以这不是重要的信息。如果这是针对第三方库的,那么用javadoc记录它可能是合适的,否则我不会。我只是给你看,让你知道你可以,如果你想的话。谢谢!这就成功了。(但是,对
distanceX
distanceY
的强制转换是多余的,因为会发生加宽转换)@LudwigvonDrake如果不强制转换其中至少一个,它将调用
int subtractExact(int x,int y)
重载并加宽结果,而不是