Calculating nth root in Java using power method

31,190

Solution 1

Since it is not possible to have arbitrary-precision calculus with double, you have three choices:

  1. Define a precision for which you decide whether a double value is an integer or not.
  2. Test whether the rounded value of the double you have is a correct result.
  3. Do calculus on a BigDecimal object, which supports arbitrary-precision double values.

Option 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
}

The problem with this approach is how to define "close enough". This is a subjective question and it depends on your requirements.

Option 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;
}

The advantage of this method is that there is no need to define a precision. However, we need to perform another pow operation so this will affect performance.

Option 3

There is no built-in method to calculate a double power of a BigDecimal. This question will give you insight on how to do it.

Solution 2

The Math.round function will round to the nearest long value that can be stored to a double. You could compare the 2 results to see if the number has an integer cubic root.

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
}

If that's inadequate you can try implementing this algorithm and stop early if the result doesn't seem to be an integer.

Solution 3

I'd go for implementing my own function to do this, possibly based on this method.

Solution 4

You can use some tricks come from mathematics field, to havemore accuracy. Like this one x^(1/n) = e^(lnx/n).

Check the implementation here: https://www.baeldung.com/java-nth-root

Solution 5

Here is the solution without using Java's Math.pow function. It will give you nearly nth root

public class NthRoot {

public static void main(String[] args) {
    try (Scanner scanner = new Scanner(System.in)) {
        int testcases = scanner.nextInt();
        while (testcases-- > 0) {
            int root = scanner.nextInt();
            int number = scanner.nextInt();
            double rootValue = compute(number, root) * 1000.0 / 1000.0;
            System.out.println((int) rootValue);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static double compute(int number, int root) {
    double xPre = Math.random() % 10;
    double error = 0.0000001;
    double delX = 2147483647;
    double current = 0.0;

    while (delX > error) {
        current = ((root - 1.0) * xPre + (double) number / Math.pow(xPre, root - 1)) / (double) root;
        delX = Math.abs(current - xPre);
        xPre = current;
    }
    return current;
}
Share:
31,190

Related videos on Youtube

Sara Alaa Khodeir
Author by

Sara Alaa Khodeir

Updated on November 19, 2021

Comments

  • Sara Alaa Khodeir
    Sara Alaa Khodeir over 2 years

    I was trying to get a cubic root in java using Math.pow(n, 1.0/3) but because it divides doubles, it doesn't return the exact answer. For example, with 125, this gives 4.9999999999. Is there a work-around for this? I know there is a cubic root function but I'd like to fix this so I can calculate higher roots.

    I would not like to round because I want to know whether a number has an integer root by doing something like this: Math.pow(n, 1.0 / 3) % ((int) Math.pow(n, 1.0 / 3)).

    • fps
      fps over 8 years
      Use BigDecimal class, which is decimal representation of real numbers with arbitrary precision.
    • fps
      fps over 8 years
      Of course there's no method to calculate nth roots in the BigDecimal class. So you'd need to implement it yourself. I'd give the newton raphson method a chance. See here.
  • Sara Alaa Khodeir
    Sara Alaa Khodeir over 8 years
    I know that this is correct, but I couldn't do that because I need to make sure that the number is an integer root, I just edited the question to include this.
  • Raman Shrivastava
    Raman Shrivastava over 8 years
    this is what is already mentioned in question. that he;s not getting exact result and dont want to round the result.
  • Manos Nikolaidis
    Manos Nikolaidis over 8 years
    @RamanShrivastava I edited the answer according to the edited question
  • Obicere
    Obicere over 8 years
    This issue has more to do with the way precision is defined for the double, not so much the method being used.
  • Sara Alaa Khodeir
    Sara Alaa Khodeir over 8 years
    @ManosNikolaidis Thank you!
  • Gary Chen
    Gary Chen almost 4 years
    You've posted two answers. Which one is more useful?