63 votes

Pourquoi std :: pow (double, int) a-t-il été supprimé de C ++11?

Tout en regardant dans le moyen Efficace pour calculer p^q (exponentiation), où q est un entier et d'examiner le C++98 et C++11 normes, j'ai remarqué qu'en apparence, l' std::pow(double, int) de surcharge a été supprimé en C++11.

En C++98 26.5/6 il a de l' double pow(double, int); signature.

En C++11 de 26,8 tout ce que je pouvais trouver était surcharges de prendre une paire de float, doubleou long double, et explicite noter que dans le cas d'un mélange de types de paramètres intégral et double, que l' pow(double, double) de surcharge doit être cueilli.

Est-ce juste une clarification de la précédente intention, ont-ils ajouté de façon erronée en C++98, étaient-ils réellement supprimé en C++11, ou quelque chose d'autre?

Évidemment, l' pow(double, int) version offre une belle opportunité d'optimisation de sorte qu'il semble étrange qu'ils seraient supprimés. Serait un compilateur toujours être conforme aux normes de fournir une telle optimisé surcharge?

82voto

Howard Hinnant Points 59526
double pow(double, int);

n'a pas été supprimée à partir de la spécification. Il a simplement été reformulé. Il vit maintenant dans [c.maths]/p11. Comment il est calculé est un détail d'implémentation. La seule C++03 signature qui a changé, c'est:

float pow(float, int);

Cela renvoie désormais double:

double pow(float, int);

Et ce changement a été fait pour les C de compatibilité.

Précisions:

26.8 [cmath] / p11 dit:

En outre, on procède à d'autres surcharges suffisant pour assurer:

  1. Si aucun argument correspondant à un double paramètre est de type long double, alors tous les arguments correspondant à double paramètres sont bien lancer à long double.

  2. Sinon, si un argument correspondant à un double paramètre a double de type ou d'un type entier, alors tous les arguments correspondant à double paramètres sont bien lancer à double.

  3. Sinon, tous les arguments correspondant à double paramètres sont bien lancer à flotteur.

Ce paragraphe implique toute une série de surcharges, y compris:

double pow(double, int);
double pow(double, unsigned);
double pow(double, unsigned long long);

etc.

Ces peut être réelle surcharges, ou peut être mis en œuvre avec limité de modèles. J'ai personnellement mis en œuvre dans les deux sens et favorisent fortement restreint l'implémentation du modèle.

Deuxième mise à jour de l'adresse de problèmes d'optimisation:

La mise en œuvre est autorisé à optimiser toute surcharge. Mais rappelons qu'une optimisation devrait être seulement ça. La version optimisée devraient revenir à la même réponse. L'expérience de responsables de l'implémentation des fonctions comme le pow est que par le temps que vous allez pour la peine de s'assurer que votre mise en œuvre de la prise d'un exposant entier donne la même réponse que la mise en virgule flottante exposant, le "optimisation" est souvent plus lent.

Comme une démonstration le programme suivant imprime pow(.1, 20) deux fois, une fois en utilisant std::pow, et la deuxième fois à l'aide d'un "optimisé" algorithme de prendre avantage de l'exposant entier:

#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';
}

Sur mon système, cette affiche:

1.0000000000000011e-20
1.0000000000000022e-20

Ou en hexadécimal:

0x1.79ca10c92422bp-67
0x1.79ca10c924232p-67

Et oui, des réalisateurs de pow vraiment ne vous inquiétez pas au sujet de tous les bits vers le bas à l'extrémité basse.

Ainsi, alors que la liberté est là pour shuffle pow(double, int) un algorithme différent, la plupart des réalisateurs, je suis conscient d'avoir abandonné cette stratégie, avec la possible exception de la vérification pour les très petites intégrale des exposants. Et dans ce cas, il est généralement avantageux de mettre que l'enregistrement dans la mise en œuvre avec la virgule flottante exposant de manière à obtenir le plus grand coup pour l'optimisation de votre buck.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X