Java中BigDecimal的BigInteger强大功能

时间:2014-08-07 12:48:25

标签: java biginteger bigdecimal

我试图获得double值的幂,其中指数非常大(Java BigInteger可以包含它(指数),例如:10 ^ 30)

也就是说,我希望找到类似 1.75 ^(10 ^ 30) 1.23 ^(34234534534222)的内容。如果输出太大,请通过获取来修改它由10 ^ 9 + 7的素数模数。

如果我想找到Integer的强大功能,我可以使用 BigInteger.modPow() 方法来获取BigInteger个参数:

( BigInteger modPow(BigInteger exponent, BigInteger m) )

据我所知,这就是我用Java获得的东西

new BigDecimal("1.5").pow(1000); // .pow() can get only integers as a parameter , but i want to pass a big number like a BigInteger 

我无法在java中为 BigDecimal 找到相应的( BigInteger.modPow()) ,或者我错过了。

有没有办法做到这一点 - 计算一个浮点数的大功率(Decimal)?

输入和输出示例:

输入:num //或1.5或任何十进制数。也可以是整数。

exponent:exp //大整数或长值

输出:num ^ exp // num to ther power exp

即计算 1.23 ^(34234534534222)

如果输出太大,则通过将模数设为10 ^ 9 + 7

的素数来修改它

2 个答案:

答案 0 :(得分:1)

Math.BigDecimal implementation of core mathematical functions有:

static java.math.BigDecimal powRound(java.math.BigDecimal x, java.math.BigInteger n) 
          Raise to an integer power and round.

这似乎正是你所需要的。有一个外部库的事实表明在java.Math中没有像这样的方法的核心实现。

作为旁注,我可以说,如果您的输入在小数位方面相当小(因此不合理),就像1.5一样,您可以在15/10进行转换并执行

(15^BigInteger)/(10^BigInteger)

modPow(BigInteger exponent, BigInteger m) BigInteger。这显然提高了计算的复杂性和数量。

答案 1 :(得分:0)

有几点需要注意。正如GáborBakos指出的那样,结果值很可能包含太多数字,甚至可以表示为BigDecimal

此外,这些数字的数字增长很快,因此计算类似2.0 34234534534222 的内容在存储方面完全超出范围(并且,正如我所假设的,就所需时间而言)。

你提到当值变得“太大”时,可以以大质数为模来计算该值。虽然你没有说明这意味着什么,但这不一定对你有帮助,因为使用modulo不会截断小数位。你必须以某种方式限制计算发生的精度。

但是,使用exponentiation by squaring的最简单实现可能粗略如下所示:

import java.math.BigDecimal;
import java.math.BigInteger;

public class BigDecimalPow {
    public static void main(String[] args) {
        BigDecimal b = new BigDecimal(1.5);
        BigInteger e = new BigInteger("325322");
        BigDecimal result = pow(b, e);
        System.out.println("Done "+result.scale());
        System.out.println(result);
    }


    /**
     * Computes d to the power of e
     * @param b The value
     * @param e The exponent
     * @return The power
     */
    private static BigDecimal pow(BigDecimal b, BigInteger e) {
        BigDecimal result = BigDecimal.ONE;
        BigDecimal p = b;
        int skipped = 0;
        while (e.compareTo(BigInteger.ZERO) > 0) {
            if (e.and(BigInteger.ONE).equals(BigInteger.ONE)) {
                if (skipped > 0) {

                    if (skipped > 29) {
                        p = pow(p, BigInteger.ONE.shiftLeft(skipped));
                    } else {
                        p = p.pow(1 << skipped);
                    }
                    skipped = 0;
                }
                result = result.multiply(p);
            }
            skipped++;
            e = e.shiftRight(1);
            System.out.println(e);
        }
        return result;
    }

}

注意:上面的实现真的简单。最有可能的解决方案对某些情况更有效,或者使用模运算来支持“更大”的数字。但是你根本不能代表(可能)34234534534222小数位,除非你有34 TB的RAM和一个long寻址的JVM,所以我怀疑会有一个解决方案满足你直到现在所说的要求 - 但是如果有人证明我错了,那就会投票+赏金......