double pow(double, int);
не был удален из спецификации. Это было просто перефразировано. Сейчас он живет в [c.math] / p11. Как это вычисляется - деталь реализации. Единственная подпись C ++ 03, которая изменилась:
float pow(float, int);
Это теперь возвращает double:
double pow(float, int);
И это изменение было сделано для совместимости с Си.
Разъяснение
26,8 [cmath] / p11 говорит:
Кроме того, должны быть дополнительные
перегрузки, достаточные для обеспечения:
Если какой-либо аргумент, соответствующий параметру double, имеет тип long double,
тогда все аргументы, соответствующие
двойные параметры эффективно приводятся
к длинному двойному.
В противном случае, если какой-либо аргумент соответствует двойному параметру
имеет тип double или целочисленный тип,
тогда все аргументы, соответствующие
двойные параметры эффективно приводятся
удвоить.
В противном случае все аргументы, соответствующие двойным параметрам
эффективно разыгрывается на плаву.
Этот параграф подразумевает целый ряд перегрузок, включая:
double pow(double, int);
double pow(double, unsigned);
double pow(double, unsigned long long);
и т.д.
Это могут быть фактические перегрузки или могут быть реализованы с помощью ограниченных шаблонов. Я лично реализовал это обоими способами и решительно поддерживаю ограниченную реализацию шаблонов.
Второе обновление для решения проблем оптимизации:
Реализация позволяет оптимизировать любую перегрузку. Но помните, что оптимизация должна быть только . Оптимизированная версия должна возвращать тот же ответ. Опыт разработчиков функций, таких как pow, заключается в том, что к тому времени, когда вы решаете, что ваша реализация, использующая интегральный показатель, дает тот же ответ, что и реализация, использующая показатель с плавающей запятой, «оптимизация» часто медленнее.
В качестве демонстрации следующая программа печатает pow(.1, 20)
дважды, один раз с использованием std :: pow, а второй раз с использованием «оптимизированного» алгоритма с использованием интегральной экспоненты:
#include <cmath>
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::setprecision(17) << std::pow(.1, 20) << '\n';
double x = .1;
double x2 = x * x;
double x4 = x2 * x2;
double x8 = x4 * x4;
double x16 = x8 * x8;
double x20 = x16 * x4;
std::cout << x20 << '\n';
}
В моей системе это печатает:
1.0000000000000011e-20
1.0000000000000022e-20
или в шестнадцатеричной записи:
0x1.79ca10c92422bp-67
0x1.79ca10c924232p-67
И да, разработчики pow действительно беспокоятся обо всех этих битах на нижнем уровне.
Так что, хотя есть свобода перетаскивать pow(double, int)
на отдельный алгоритм, большинство разработчиков, о которых я знаю, отказались от этой стратегии, за возможным исключением проверки очень малых интегральных показателей. И в этом случае, как правило, выгодно помещать эту проверку в реализацию с показателем с плавающей запятой, чтобы получить максимальную отдачу от вашей оптимизации.