Объектно-ориентированное программирование на Java. Платформа Java SE - страница 24
Этот счетчик отслеживает, сколько х мы умножаем и накапливаем с помощью z.
И мы должны выполнять тело цикла ровно y раз, пока i не станет равен y.
Затем мы выходим и возвращаем накопленное значение в z.
Давайте проанализируем это снова.
x в степени y равно 1, если y равно 0.
А если y строго больше 0, то x в степени y равно x умножить на x в степени y минус 1.
Это то, что в математике называется рекуррентным уравнением.
И мы можем написать это на Java в виде вызова функции power.
Если y равно 0, возвращаем 1.
Иначе, возвращаем x умножить на вызов этой же функции с x и y минус 1.
Таким образом, тот же метод, который мы определили с помощью цикла, может быть определен с помощью рекурсии.
Оба эти способа эквивалентны.
Но рекурсия позволяет записать сложное поведение простым способом, который потребует довольно сложного программирования при использовании циклов.
Рекурсию можно сравнить с матрешкой.
Чтобы понять это вернемся к рекурсивному методу, который мы определили.
И давайте упростим последовательно вызов этого метода для небольшой степени, чтобы увидеть, что происходит.
Начнем с x в 3 степени.
Мы можем заменить вызов метода, используя определение метода.
Таким образом, мы пишем весь код метода, подставляя вместо y 3.
И в этой последовательности выражений мы переходим от вызова метода с параметрами (x, 3) к вызову метода с параметрами (x, 2).
Пишем весь код метода, подставляя вместо y 2.
И в этой последовательности выражений, мы перешли от вызова метода с параметрами (x, 2) к вызову метода с параметрами (x, 1).
И переходим к вызову метода с параметрами (x, 0).
x в степени 0 равно 1.
Теперь нам нужно собрать все вместе.
power (x, 3) равно x умножить на power (x, 2).
А power (x, 2) равно x умножить на power (x, 1).
А power (x, 1) равна x умножить на power (x, 0), что равно 1.
Таким образом, мы получаем x умножить на x умножить на x умножить на 1.
Так работает рекурсия – сначала мы спускаемся как по лестнице вниз, а затем поднимаемся опять наверх.
Это изображение коробки с медсестрой, держащей меньшую коробку с тем же изображением.
Так что в теории, могут быть бесконечные медсестры и бесконечные коробки.
Но на практике нет бесконечных коробок, потому что изображение имеет некоторое разрешение, и мы не можем опуститься ниже 1 пикселя.
Таким образом, существует конечное число коробок.
Когда мы что-то вычисляем, мы должны заботиться о том, чтобы не создавать нежелательные бесконечные вычисления, которые нарушают нормальный поток вычислений.
Давайте посмотрим, что произойдет, когда мы что-то неправильно программируем.
Давайте рассмотрим, опять наш рекурсивный метод вычисления степени числа.
И давайте вызовем power (x, -2) для некоторого заданного x.
Для этого мы можем заменить вызов метода кодом.
В результате мы перейдем к вызову метода power (x, -3).
В методе power (x, -3) мы перейдем к вызову метода power (x, -4).
И так далее. Без конца.
Мы получим бесконечные вычисления в теории.
На практике мы получим переполнение в какой-то момент и ошибку.
Что же мы сделали не так?
В этом случае мы не соблюдали комментарий, что y должно быть больше или равно 0.
Поэтому мы должны учитывать две важные вещи.
Во-первых, рекурсия хороша, но мы можем перейти к бесконечным вычислениям.
И во-вторых, чтобы избежать этого, мы должны понять условия, при которых рекурсивный метод фактически завершается.
Может быть определенное количество рекурсивных вызовов, но в какой-то момент, нам нужно достичь не рекурсивного случая.