如何在Java中对BigDecimal进行分数处理?

时间:2010-08-26 21:43:11

标签: java formula bigdecimal pow

在我的小项目中,我需要做一些像Math.pow(7777.66,5555.44)这样的东西只有非常大的数字。我遇到了一些解决方案:

  • 使用双倍 - 但数字太大
  • 使用BigDecimal.pow但不支持分数
  • 使用X ^(A + B)= X ^ A * X ^ B公式(B是第二个数字的余数),但是再次不支持大X或大A,因为我仍然转换为double
  • 使用某种泰勒级数算法或类似的东西 - 我不是很擅长数学,所以如果我找不到任何解决方案(某些库或(A + B)的公式),这个是我的最后一个选项^(C + d))。

任何人都知道图书馆或简单的解决方案?我想很多人都处理同样的问题...

P.S。 我发现了一些名为ApFloat的图书馆声称大约会这样做,但我得到的结果非常近似,甚至8 ^ 2也给了我60 ...

3 个答案:

答案 0 :(得分:24)

1.7976931348623157E308(Double.MAX_VALUE)下的参数解决方案,但支持数字为MILLIONS的结果:

由于double支持的数字最多为MAX_VALUE(例如,100!in double看起来像这样:9.332621544394415E157),使用BigDecimal.doubleValue()没有问题。但是你不应该只做Math.pow(double,double),因为如果结果大于MAX_VALUE,你将获得无穷大。 SO:使用公式X ^(A + B)= X ^ A * X ^ B将计算分离为两个幂,使用BigDecimal.pow将大,使用Math的小(第二个参数的剩余部分)。战争,然后繁殖。 X将被复制到DOUBLE - 确保它不大于MAX_VALUE,A将是INT(最大值2147483647但BigDecimal.pow不支持超过10亿的整数),B将是double,总是小于1。这样你就可以做到以下几点(忽略我的私有常量等):

    int signOf2 = n2.signum();
    try {
        // Perform X^(A+B)=X^A*X^B (B = remainder)
        double dn1 = n1.doubleValue();
        // Compare the same row of digits according to context
        if (!CalculatorUtils.isEqual(n1, dn1))
            throw new Exception(); // Cannot convert n1 to double
        n2 = n2.multiply(new BigDecimal(signOf2)); // n2 is now positive
        BigDecimal remainderOf2 = n2.remainder(BigDecimal.ONE);
        BigDecimal n2IntPart = n2.subtract(remainderOf2);
        // Calculate big part of the power using context -
        // bigger range and performance but lower accuracy
        BigDecimal intPow = n1.pow(n2IntPart.intValueExact(),
                CalculatorConstants.DEFAULT_CONTEXT);
        BigDecimal doublePow =
            new BigDecimal(Math.pow(dn1, remainderOf2.doubleValue()));
        result = intPow.multiply(doublePow);
    } catch (Exception e) {
        if (e instanceof CalculatorException)
            throw (CalculatorException) e;
        throw new CalculatorException(
            CalculatorConstants.Errors.UNSUPPORTED_NUMBER_ +
                "power!");
    }
    // Fix negative power
    if (signOf2 == -1)
        result = BigDecimal.ONE.divide(result, CalculatorConstants.BIG_SCALE,
                RoundingMode.HALF_UP);

结果示例:

50!^10! = 12.50911317862076252364259*10^233996181

50!^0.06 = 7395.788659356498101260513

答案 1 :(得分:0)

Exponents = logarithms。

查看Logarithm of a BigDecimal

答案 2 :(得分:0)

在MIT许可下发布的big-math库具有一个简单的静态助手BigDecimalMath.log(BigDecimal, MathContext),用于记录日志以及BigDecimal不包含的许多其他功能。使用非常简单,并且有大量基准数据可用来比较性能。