2 回答
TA贡献1865条经验 获得超7个赞
无需使用 long,您可以在实际执行操作之前检查两个整数的乘法是否会溢出:
int a = 500000; //or -500000
int b = 900000; //or -900000
System.out.println(isOverflowOrUnderflow(a, b));
//Returns true if multiplication of a, b results in an overflow or underflow..
public static boolean isOverflowOrUnderflow(int a, int b) {
return ((a > Integer.MAX_VALUE / b) || (a < Integer.MIN_VALUE / b) || ((a == -1) && (b == Integer.MIN_VALUE)) || ((b == -1) && (a == Integer.MIN_VALUE)));
}
使用您的代码的示例:
public class Main {
public static void main (String[] args) {
int N = Integer.parseInt(args[0]); //Where args[0] = "1000000"..
int sum = 0;
long R;
for (int i = 1; i <= N; i++) {
if (Main.isOverflowOrUnderflow(i, i)) {
System.err.println("Overflow at i = " + i);
System.exit(1);
}
R = i * i;
sum += R;
}
System.out.println(sum);
}
public static boolean isOverflowOrUnderflow(int a, int b) {
return ((a > Integer.MAX_VALUE / b) || (a < Integer.MIN_VALUE / b) || ((a == -1) && (b == Integer.MIN_VALUE)) || ((b == -1) && (a == Integer.MIN_VALUE)));
}
}
输出:
Overflow at i = 46341
Command exited with non-zero status 1
TA贡献2003条经验 获得超2个赞
您有 2 个错误:
R = i * i仍然使用数学执行乘法,并且在乘法已经溢出到负值之前int不会将值扩大到。long
您需要将其中至少一个转换long为R = i * (long) i.
if (i != R / i)不是溢出的正确测试。只需检查该long值是否超出范围int:if (r > Integer.MAX_VALUE)
static int sumOfSquares(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
long r = i * (long) i;
if (r > Integer.MAX_VALUE) {
System.err.println("Overflow at i = " + i);
System.exit(1);
}
sum += r;
}
return sum;
}
测试
System.out.println(sumOfSquares(2));
System.out.println(sumOfSquares(3));
System.out.println(sumOfSquares(1000000));
输出
5
14
Overflow at i = 46341
另一种防止溢出的方法是使用Math.multiplyExact()andMath.addExact()方法。
static int sumOfSquares(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
int r = Math.multiplyExact(i, i);
sum = Math.addExact(sum, r);
}
return sum;
}
输出
5
14
Exception in thread "main" java.lang.ArithmeticException: integer overflow
at java.base/java.lang.Math.addExact(Math.java:825)
at Test.sumOfSquares(Test.java:12)
at Test.main(Test.java:6)
如果您想要更好的错误消息,或者捕获异常:
static int sumOfSquares(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
try {
int r = Math.multiplyExact(i, i);
sum = Math.addExact(sum, r);
} catch (@SuppressWarnings("unused") ArithmeticException ignored) {
System.err.println("Overflow at i = " + i);
System.exit(1);
}
}
return sum;
}
输出
5
14
Overflow at i = 1861
添加回答
举报