Возведение в степень без циклов и условий

А что, если в D можно возвести в степень не пользуясь циклами и условиями? Конечно, тут я должен сказать, что возвести получиться только в целую неотрицательную степень, но все же это возможно…

Например, это можно осуществить так:

import std.algorithm;
import std.range;
import std.stdio;

void pow(int x, int y)
{
	auto N = 1;
	N = cycle(x)
				.take(y)
				.reduce!((a,b) => a * b);
	return N;
}

void main()
{
	pow(2, 3).writeln;
}

Как это работает?

Легко и просто! Используется простое математическое определение степени, которое гласит, что степень числа – это количество последовательных умножений этого числа на самого себя. Исключение из этого определения – это нулевая степень, которая означает, что число ни разу не умножалось, а исходя из конвенции математиков, такая степень равна единице.

Причем тут это определение?

А при том, что мы сделали буквальную его реализацию: взяли бесконечный набор элементов, состоящий только из одного числа (с помощью алгоритма cycle из std.range), потом взяли его ровно столько раз, сколько мы должны перемножить число на само себя (алгоритм take из std.range), а затем воспользовались свертывающим алгоритмом reduce.

Последний алгоритм берет функцию, некоторое стартовое значение и диапазон, проходит по диапазону функцией, накапливая каждый результат попарного применения функции к стартовому значению и каждому элементу списка; в итоге под действием умножения список сворачивается в одно компактное произведение, которое и будет являться степенью.

Конечно, объяснение reduce в моем исполнении несколько туманно, но не поленитесь и загляните в std.algorithm, там очень наглядные и простые примеры использования этого гениального алгоритма (Также, вы можете обратить внимание на то, что эта функция есть во многих языках программирования, особенно в функциональных. И честно говоря, она мне напоминает функцию foldl из Haskell).

В целом, эта статья лишь забавный пример, но тем не менее она иллюстрирует некоторый способ функционального мышления и показывает, что даже чисто императивный код может быть выражен (хоть и не всегда) в функциональных терминах.

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

Добавить комментарий