为了账号安全,请及时绑定邮箱和手机立即绑定

Java 手动溢出处理不需要的输出

Java 手动溢出处理不需要的输出

catspeake 2022-01-19 17:11:32
我有以下程序平方和 1^2 + 2^2 + … + N^2 计算为: 示例输出:java SumSquares 2 = 5java SumSquares 3 = 14java SumSquares 1000000 = 333333833333500000这是我到目前为止所拥有的:        int N = Integer.parseInt(args[0]);        int sum = 0;        long R;        for (int i = 1; i <= N; i++) {            R = i * i;            if (i != R / i) {                System.err.println("Overflow at i = " + i);                System.exit(1);            }            sum += R;        }        System.out.println(sum);我的输出是 java SumSquares 100000000 Overflow at i = 46341由于 46341^2 通过了 MAX INT。我只是无法让程序输出以下说明,任何关于如何获取的想法java SumSquares 100000000 在 i = 3024616 处溢出我可以将整数更改为长整数,但这会否定溢出检查的需要。从规格:计算会溢出。我需要通过检查新总和是否(严格)小于旧总和来准确确定总和中发生溢出的点。java SumSquares 100000000 在 i = 3024616 处溢出请注意,以上必须通过循环中的一般溢出处理来实现,而不是通过某些预先确定的输入测试来实现。因此,当用于求和的整数类型被更大的类型替换时,您的程序将完全使用新的扩展范围。只是为了澄清:是否有可能获得输出java SumSquares 100000000 在 i = 3024616 处溢出根据规范。
查看完整描述

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


查看完整回答
反对 回复 2022-01-19
?
湖上湖

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


查看完整回答
反对 回复 2022-01-19
  • 2 回答
  • 0 关注
  • 133 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信