使用幂方法计算Java中的第n个根

我试图使用Math.pow(n, 1.0/3)在java中获得立方根Math.pow(n, 1.0/3)但因为它除了双精度数,所以它不会返回确切的答案。 例如,对于125,这给出了4.9999999999。 有解决办法吗? 我知道有一个立方根函数但我想解决这个问题,所以我可以计算更高的根。

我不想舍入,因为我想知道一个数字是否具有整数根,通过这样做: Math.pow(n, 1.0 / 3) % ((int) Math.pow(n, 1.0 / 3))

Math.round函数将舍入到可以存储为double的最近的long值。 您可以比较2个结果以查看该数字是否具有整数立方根。

 double dres = Math.pow(125, 1.0 / 3.0); double ires = Math.round(dres); double diff = Math.abs(dres - ires); if (diff < Math.ulp(10.0)) { // has cubic root } 

如果这还不够,你可以尝试实现这个算法并在结果看起来不是整数时提前停止。

由于不可能使用double进行任意精度计算,因此您有三种选择:

  1. 定义一个精度,您可以根据该精度来确定double值是否为整数。
  2. 测试double的舍入值是否是正确的结果。
  3. BigDecimal对象上进行微积分,它支持任意精度的double值。

选项1

 private static boolean isNthRoot(int value, int n, double precision) { double a = Math.pow(value, 1.0 / n); return Math.abs(a - Math.round(a)) < precision; // if a and round(a) are "close enough" then we're good } 

这种方法的问题是如何定义“足够接近”。 这是一个主观问题,取决于您的要求。

选项2

 private static boolean isNthRoot(int value, int n) { double a = Math.pow(value, 1.0 / n); return Math.pow(Math.round(a), n) == value; } 

此方法的优点是无需定义精度。 但是,我们需要执行另一个pow操作,因此这会影响性能。

选项3

没有内置方法来计算BigDecimal的双倍幂。 这个问题将为您提供有关如何做到这一点的见解。

我可以基于这种方法来实现我自己的function。

我写了这个方法来计算floor(x^(1/n)) ,其中x是非负BigIntegern是正整数。 不久之前,我现在无法解释为什么会有效,但我有理由相信,当我写这篇文章时,我很高兴能够合理地快速给出正确答案。

要查看x是否是精确的n-th幂,您可以检查提升到幂n的结果是否再次为您提供x

 public static BigInteger floorOfNthRoot(BigInteger x, int n) { int sign = x.signum(); if (n <= 0 || (sign < 0)) throw new IllegalArgumentException(); if (sign == 0) return BigInteger.ZERO; if (n == 1) return x; BigInteger a; BigInteger bigN = BigInteger.valueOf(n); BigInteger bigNMinusOne = BigInteger.valueOf(n - 1); BigInteger b = BigInteger.ZERO.setBit(1 + x.bitLength() / n); do { a = b; b = a.multiply(bigNMinusOne).add(x.divide(a.pow(n - 1))).divide(bigN); } while (b.compareTo(a) == -1); return a; } 

要使用它:

 System.out.println(floorOfNthRoot(new BigInteger("125"), 3)); 

编辑阅读上面的评论后,我现在记住,这是第n个根的Newton-Raphson方法。 Newton-Raphson方法具有二次收敛性(在日常语言中意味着它很快)。 您可以尝试使用具有数十位数字的数字,您应该在几分之一秒内得到答案。

您可以调整该方法以使用其他数字类型,但在我看来, doubleBigDecimal不适合这种类型的事情。

那么这是在这种情况下选择的一个很好的选择。 你可以依靠这个 –

  System.out.println(" "); System.out.println(" Enter a base and then nth root"); while(true) { a=Double.parseDouble(br.readLine()); b=Double.parseDouble(br.readLine()); double negodd=-(Math.pow((Math.abs(a)),(1.0/b))); double poseve=Math.pow(a,(1.0/b)); double posodd=Math.pow(a,(1.0/b)); if(a<0 && b%2==0) { String io="\u03AF"; double negeve=Math.pow((Math.abs(a)),(1.0/b)); System.out.println(" Root is imaginary and value= "+negeve+" "+io); } else if(a<0 && b%2==1) System.out.println(" Value= "+negodd); else if(a>0 && b%2==0) System.out.println(" Value= "+poseve); else if(a>0 && b%2==1) System.out.println(" Value= "+posodd); System.out.println(" "); System.out.print(" Enter '0' to come back or press any number to continue- "); con=Integer.parseInt(br.readLine()); if(con==0) break; else { System.out.println(" Enter a base and then nth root"); continue; } } 

这是一个非常丑陋的黑客,但你可以通过缩进来达到其中一些。

 System.out.println(Math.sqrt(Math.sqrt(256))); System.out.println(Math.pow(4, 4)); System.out.println(Math.pow(4, 9)); System.out.println(Math.cbrt(Math.cbrt(262144))); Result: 4.0 256.0 262144.0 4.0 

这将给你每n ^ 3个立方体和每n ^ 2个根。

您可以使用来自数学领域的一些技巧,以获得更高的准确性。 像这样一个x ^(1 / n)= e ^(lnx / n)。

请查看此处的实施: https : //www.baeldung.com/java-nth-root