Временная сложность для квадратного корня с использованием метода Ньютона

Я написал java-программу для нахождения квадратного корня из заданного числа с использованием метода Ньютона. Эта программа работает точно так, как предполагалось. Но я плохо разбираюсь во временной сложности.

Итак, не могли бы вы сказать мне, какова временная сложность следующей программы. Приветствуются предложения по его улучшению.

Что такое нотация Big O для метода sqrt?

/**Find square root of a number using Newton's method**/
/**Specify number of correct precision required in a square root**/
/**Also specify maxIterations limit so that program won't go into into infinity loop**/
import java.util.*;
public class SqrtNewton{
        public static void main(String[] args){
            try{
                long startTime = System.nanoTime();
                Scanner scanner = new Scanner(System.in);
                //Number for which square root has to be found
                System.out.println("Enter number - ");
                long number = scanner.nextLong();
                //Maximum no of iterations if program does not found Square root untill then
                int maxIterations = 40; 
                //precision value to untill correct square root is required
                int precision = 3;
                //Value of x to start with for newton's method
                double x = 1;
                //Negative numbers do not have square roots
                if (number < 0) throw new IllegalArgumentException("Provided value is invalid");
                //iteration start
                int itr = 0;
                //epsilon value to check equality of double value untill given precision
                double epsilon = Math.pow(10,-precision);
                double squareRoot = sqrt(number,maxIterations,x,itr,epsilon);
                System.out.println("Square Root Of "+number+" With correct precision "+precision+" is :- "+squareRoot);
                System.out.printf("Square Root Of %d With correct precision %d is :- %."+precision+"f",number,precision,squareRoot);
                System.out.println();
                long endTime = System.nanoTime();
                System.out.println("Total Running Time - "+(endTime - startTime));
            }catch(Exception e){
                //e.printStackTrace();
                System.err.println("Exception - "+e.getMessage());
            }
        }
        private static double sqrt(long number,int maxIterations,double x,int itr,double epsilon) throws MaxIterationsReachedException{
            if(itr >= maxIterations){
                throw new MaxIterationsReachedException(maxIterations);
            }else{
                double x1 = (x + (number/x))/2;
                /**To check equality of double number untill given precision**/
                /**This will check 1.1333334 - 1.1333334 < 0.000001(if precision is 6)**/
                if(Math.abs(x1 - x) <=  epsilon){
                    System.out.println("Total Iterations - "+itr);
                    return x1;
                }
                else
                    return sqrt(number,maxIterations,x1,++itr,epsilon);
            }
        }
}


class MaxIterationsReachedException extends Exception{  
 MaxIterationsReachedException(int maxIterations){
     super("Maximum iterations limit "+maxIterations+" reached Increase maxIterations limit if required");
 }
} 

person Dhaval Padaya    schedule 28.04.2019    source источник
comment
В чем вопрос? Вы спрашиваете о том, что является большим O в вашем методе? Или вы ищете проверку кода?   -  person phflack    schedule 28.04.2019


Ответы (2)


Я бы сказал, что сложность составляет O (n), где n - это maxIterations. Вам не нужно писать этот алгоритм рекурсивно, вы можете использовать такой цикл:

private static double sqrt2(long number, int maxIterations, double x, int itr, double epsilon)
        throws MaxIterationsReachedException {
    double x1 = (x + (number / x)) / 2;
    while (Math.abs(x1 - x) > epsilon) {
        if (itr >= maxIterations) {
            throw new MaxIterationsReachedException(maxIterations);
        }
        x = x1;
        x1 = (x + (number / x)) / 2;
        itr++;
    }
    System.out.println("Total Iterations - " + itr);
    return x1;
}
person Nguyen Tan Bao    schedule 28.04.2019
comment
Есть ли разница в производительности между рекурсивным подходом и циклом while? Я знаю, что для каждого рекурсивного вызова будет создаваться новый стек, но я хочу узнать, как это повлияет на производительность программы? - person Dhaval Padaya; 28.04.2019
comment
Производительность при рекурсивном вызове будет немного хуже, поскольку, как вы упомянули: jvm должен выделить новый стек, что также требует времени и памяти. Если вы установите слишком большое значение maxIterations, вы можете получить ошибку переполнения стека, чего никогда не произойдет, если вы используете цикл. - person Nguyen Tan Bao; 28.04.2019
comment
Известно, что метод Ньютона для извлечения квадратного корня имеет логарифмическую сложность времени выполнения. - person razz; 04.06.2020

Ваш код представляет собой реализацию метода Ньютона для решения x^2-c = 0.

Известно, что это имеет квадратичную сходимость, что означает, что если вы хотите D цифр точности, это займет примерно log (D) итераций, хотя это зависит от вашего первоначального предположения для квадратного корня сложным образом. Вы можете прочитать доказательство квадратичной сходимости в Википедии: https://en.wikipedia.org/wiki/Newton%27s_method, который включает предварительные условия для квадратичной сходимости.

Поскольку ваше начальное предположение всегда равно «1», это, вероятно, не будет удовлетворять условиям квадратичной сходимости, и, если мне не изменяет память, это означает, что для больших x будет медленная сходимость для некоторых шагов, за которой следует быстрая квадратичная сходимость. Разработка деталей фактической временной сложности довольно сложна и, вероятно, выходит за рамки того, что вы хотите.

person Paul Hankin    schedule 28.04.2019
comment
Можете ли вы поделиться каким-либо методом поиска наилучшего начального предположения для более быстрой сходимости? - person Dhaval Padaya; 28.04.2019