【问题标题】:Java ArithmeticException BigInteger would overflow supported rangeJava ArithmeticException BigInteger 会溢出支持的范围
【发布时间】:2015-04-09 19:22:19
【问题描述】:

我正在研究一种算法来检查数字是否为素数并且需要处理非常大的数字,因此我正在使用 BigInteger 类。问题是抛出此异常ArithmeticException BigInteger 会溢出支持的范围

Exception in thread "main" java.lang.ArithmeticException: BigInteger would overflow supported range
    at java.math.BigInteger.reportOverflow(Unknown Source)
    at java.math.BigInteger.checkRange(Unknown Source)
    at java.math.BigInteger.<init>(Unknown Source)
    at java.math.BigInteger.shiftLeft(Unknown Source)
    at java.math.BigInteger.pow(Unknown Source)
    at Kitas.main(Kitas.java:118)

以及抛出异常的那一行:

b = BigInteger.valueOf(2).pow((int) (35*(Math.pow(2, counter))));

一旦计数器的值达到 26,就会引发异常。

【问题讨论】:

    标签: java range overflow biginteger arithmeticexception


    【解决方案1】:
    (int) (35 * Math.pow(2, 26)) == (int) (2348810240d) = Integer.MAX_VALUE
    

    结果是您尝试将 2 提高到的幂是 Integer.MAX_VALUE,因此结果将超过 Integer.MAX_VALUE 二进制数字。 BigInteger 不够大,存储这么大的数字是非常不切实际的。

    Java 中没有任何东西可以让您测试这么大的数字的素数。

    【讨论】:

      【解决方案2】:

      BigInteger 使用int[] 来存储数组的值。这意味着该数字不能大于 2^(Integer.Max_Value),因为任何大于该数字的值都会使数组的索引(存储在单个 int 中)大于数组的最大大小。

      在 26 时,您存储的数字是:

      2^(35*[2^26]) = 2^2348810240 
      

      这里使用的2的幂(2,348,810,240)略大于(2^31-1),这是由于BigInteger内部存储的实现,可以存储在BigInteger中的最大值。超过 26 的计数器只会使这个问题变得更糟。

      如果您真的需要处理这么大的数字,您可能必须编写自己的 BigInteger 版本,它使用其他东西来存储它的值,从而允许更多的存储空间。也许像这样的二维数组:int[][] storage,因为它可以保存高达 2^(2^(2^32-1)-1) 的值。如果您需要更多,您可以继续增加数组的维度,直到您的计算机内存不足 - 如果完全填充 int[][] 还不会这样做(我怀疑它会这样做)。

      请参阅documentation 了解更多信息。

      【讨论】:

        猜你喜欢
        • 2021-07-13
        • 1970-01-01
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多