Функция<pow
>эффективно вычисляет интегральную мощность времени компиляции базы времени выполнения.
<#include<boost/math/special_functions/pow.hpp>
>
namespace boost { namespace math {
template <int N, typename T>
calculated-result-type pow(T base);
template <int N, typename T, class Policy>
calculated-result-type pow(T base, const Policy& policy);
}}
Вычисление мощности числа с показателем, известным во время компиляции, является общей потребностью для программистов. В таких случаях обычный метод заключается в том, чтобы избежать накладных расходов, подразумеваемых функциями<pow
>,<powf
>и<powl
>C, путем жесткого кодирования выражения, такого как:
double result = base*base*base*base*base*base*base*base;
Тем не менее, этот вид выражения не совсем читаемый (знание значения экспоненты включает в себя подсчет количества случаевоснования), подверженный ошибкам (легко забыть случай), синтаксически громоздкий и неоптимальный с точки зрения производительности.
Функция боу-фунта. Математика помогает написать это выражение вместе с решением всех проблем, перечисленных выше:
double result = pow<8>(base);
Выражение теперь короче, легче читать, безопаснее и даже быстрее. Действительно,<pow
>вычислит выражение таким образом, что только продукты log2(N) сделаны для мощности N. Например, в приведенном выше примере результирующее выражение будет таким же, как если бы мы написали это, только с одним вычислением каждой одинаковой субэкспрессии:
double result = ((base*base)*(base*base))*((base*base)*(base*base));
Всего было вычислено 3 различных продукта.
Тип возврата этих функций вычисляется с использованием правил расчета типа результата. Например:
- Если<
float
>, то<float
>— это<float
>.
- Если T<
longdouble
>, то тип возврата<longdouble
>.
- В противном случае тип возврата будет<
double
>.
Конечный аргументПолитикаявляется необязательным и может использоваться для контроля поведения функции: как она обрабатывает ошибки, какой уровень точности использовать и т. д. См. документациюдля более подробной информации.
При использовании<pow
>могут возникнуть две ошибки:
- В случае нулевого основания и отрицательного показателя возникаетoverflow_error, так как эта операция является делением на 0 (она равна 1/0).
- В случае нулевой базы и нулевой экспоненты происходитindeterminate_result_error, поскольку результат этой операции является неопределенным. Эти ошибки следуют общей политике обработки ошибок. Математика.
Политика ошибки переполнения по умолчанию<throw_on_error
>. Призыв<pow<-2>(0)
>приведет к исключению<std::overflow_error
>. Как показано в приведенной выше ссылке, могут использоваться другие политики обработки ошибок:
- <
errno_on_error
>: Устанавливает<::errno
>до<ERANGE
>и возвращает<std::numeric_limits<T>::infinity()
>.
- <
ignore_error
>: Возвращение<std::numeric_limits<T>::infinity()
>.
- <
user_error
>: Возвращает результат<boost::math::policies::user_overflow_error
>: эта функция должна быть определена пользователем.
По умолчанию неопределённая политика ошибок результата<ignore_error
>, которая для этой функции возвращает 1, поскольку это наиболее часто выбираемый результат для мощности 0. Здесь снова могут использоваться другие политики обработки ошибок:
- <
throw_on_error
>: Бросает<std::domain_error
>
- <
errno_on_error
>: ставит<::errno
>на<EDOM
>и возвращает 1.
- <
user_error
>: Возвращает результат<boost::math::policies::user_indeterminate_result_error
>: эта функция должна быть определена пользователем.
Вот пример настройки обработки ошибок, где мы хотим указать результат, который должен быть возвращен в случае ошибки. Таким образом, мы будем использовать политику<user_error
>, передавая в качестве второго аргумента пример политики переполнения_ошибки, сформулированной в<user_error
>:
namespace boost { namespace math { namespace policies {
template <class T>
T user_overflow_error(const char*, const char*, const T&)
{ return -1; }
}}}
using boost::math::policies;
double result = pow<-5>(base, policy<overflow_error<user_error> >());
if (result == -1)
{
}
Другой способ — переопределить политику по умолчанию<overflow_error
>с помощью BOOST_MATH_OVERFLOW_ERROR_POLICY. Макро. Как только функция<user_overflow_error
>определена выше, мы можем достичь такого же результата:
#define BOOST_MATH_OVERFLOW_ERROR_POLICY user_error
#include <boost/math/special_functions/pow.hpp>
double result = pow<-5>(base);
Бруно Лаланд представил это дополнение к Boost. Математика.
Спасибо Joaquín López Muñoz и Скотту МакМюррею за помощь в улучшении реализации.
Д.Е. КнутThe Art of Computer Programming, Vol. 2: Seminumerical Algorithms, 2nd ed., Addison-Wesley, Reading, MA, 1981