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
为了防止错误结果溢出,请使用
数学方法
“精确”方法:
- 一,
- 一,
- 一,
- 一,
- 一,
- 一,
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)
重载并加宽结果,而不是