java - 使用 BigDecimals 计算 p 的 n 次方根

标签 java bigdecimal

我目前正在尝试按照此处所述解决此问题:

http://uva.onlinejudge.org/external/1/113.pdf

计划是实现一个递归函数来导出解决方案。这里的部分代码来自Rosetta代码,用于确定n次方根。

// Power of Cryptography 113

import java.util.Scanner;
import java.math.BigDecimal;
import java.math.RoundingMode;

// k can be 10^9 
// n <= 200
// p <= 10^101

class crypto { 
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()) {
            // Given two integers (n,p)
            // Find k such k^n = p
            int n = in.nextInt();
            BigDecimal p = in.nextBigDecimal();
            System.out.println(nthroot(n,p));
        }
    }

    public static BigDecimal nthroot(int n, BigDecimal A) {
        return nthroot(n, A, .001);
    }

    public static BigDecimal nthroot(int n, BigDecimal A, double p) {
        if(A.compareTo(BigDecimal.ZERO) < 0) return new BigDecimal(-1);
        // we handle only real positive numbers
        else if(A.equals(BigDecimal.ZERO)) {
            return BigDecimal.ZERO;
        }
        BigDecimal x_prev = A;
        BigDecimal x = A.divide(new BigDecimal(n));  // starting "guessed" value...
        BigDecimal y = x.subtract(x_prev);

        while(y.abs().compareTo(new BigDecimal(p)) > 0) {
            x_prev = x;
            BigDecimal temp = new BigDecimal(n-1.0);
            x = (x.multiply(temp).add(A).divide(x.pow(temp.intValue())).divide(new BigDecimal(n)));
        }
        return x;
    }
}

这是生成的错误代码:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)
at crypto.nthroot(crypto.java:38)
at crypto.nthroot(crypto.java:24)
at crypto.main(crypto.java:19)

最佳答案

这里有人要工作代码片段吗?我们开始吧:

public final class RootCalculus {

  private static final int SCALE = 10;
  private static final int ROUNDING_MODE = BigDecimal.ROUND_HALF_DOWN;

  public static BigDecimal nthRoot(final int n, final BigDecimal a) {
      return nthRoot(n, a, BigDecimal.valueOf(.1).movePointLeft(SCALE));
  }

  private static BigDecimal nthRoot(final int n, final BigDecimal a, final BigDecimal p) {
    if (a.compareTo(BigDecimal.ZERO) < 0) {
      throw new IllegalArgumentException("nth root can only be calculated for positive numbers");
    }
    if (a.equals(BigDecimal.ZERO)) {
        return BigDecimal.ZERO;
    }
    BigDecimal xPrev = a;
    BigDecimal x = a.divide(new BigDecimal(n), SCALE, ROUNDING_MODE);  // starting "guessed" value...
    while (x.subtract(xPrev).abs().compareTo(p) > 0) {
        xPrev = x;
        x = BigDecimal.valueOf(n - 1.0)
              .multiply(x)
              .add(a.divide(x.pow(n - 1), SCALE, ROUNDING_MODE))
              .divide(new BigDecimal(n), SCALE, ROUNDING_MODE);
    }
    return x;
  }

  private RootCalculus() {
  }
}

只需将 SCALE 设置为您需要的计算精度即可。

关于java - 使用 BigDecimals 计算 p 的 n 次方根,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22695654/

相关文章:

java - 在另一个 jar 中运行外部 jar

java - 为什么我的异常不会打印出它的打印语句? ( java )

java - 如何动态返回每个节点的一组对象?

Java 集合排序 BigDecimal

java - 执行涉及非终止 BigDecimal 的算术

java spring单元测试失败,无法加载ApplicationContext

javac : command not found

biginteger - 如何计算 BigDecimal 中的数字?

ruby-on-rails - Ruby on Rails nil 不能被强制转换为 BigDecimal

java - 将 BigDecimal 舍入为 *always* 有两位小数