[英]distanceTo() integer overflow?
為防止溢出導致不正確的結果,請使用Math
“精確”方法:
Math.addExact(int x, int y)
1Math.subtractExact(int x, int y)
1Math.multiplyExact(int x, int y)
1Math.incrementExact(int a)
1Math.decrementExact(int a)
1Math.negateExact(int a)
1Math.toIntExact(long value)
1)或long
變體。
如果發生溢出,這些方法將拋出ArithmeticException
。
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
數學來最小化溢出的可能性。
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
期間丟棄小數點時,精度可能會丟失。
首先你可以使用斜邊function。
然后 integer 溢出可能發生在遠處( -
)。
解決方案是使用double,因為最終結果是使用浮點數function計算的。
結果可能與sqrt(2)*2*Integer.MAX_VALUE
一樣大,也會溢出。
所以:
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?
}
或者更整潔(就像 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?
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.