Définitions de sqrt, sin, cos, pow etc. dans cmath
, y a des définitions de fonctions comme l'sqrt()
, sin()
, cos()
, tan()
, log()
, exp()
(ces de mathématiques.h / cmath) disponible ?
, je voulais juste savoir comment ils fonctionnent.
7 réponses
C'est une question intéressante, mais la lecture de sources de bibliothèques efficaces ne vous mènera pas très loin à moins que vous ne connaissiez la méthode utilisée.
Voici quelques conseils pour vous aider à comprendre les méthodes classiques. Mes informations ne sont en aucun cas exactes. Les méthodes suivantes ne sont que les méthodes classiques, des implémentations particulières peuvent utiliser d'autres méthodes.
- les tables de recherche sont fréquemment utilisées
- les fonctions trigonométriques sont souvent implémentées via algorithme CORDIC (soit sur le processeur, soit avec une bibliothèque). Notez que généralement le sinus et le cosinus sont calculés ensemble, je me suis toujours demandé pourquoi la bibliothèque C standard ne fournit pas de fonction
sincos
. - Les Racines Carrées utilisent la méthode de Newton avec quelques astuces d'implémentation astucieuses: vous trouverez peut-être quelque part sur le web un extrait du code source de Quake avec une implémentation 1 / sqrt(x) époustouflante.
- Exponentielles et logarithmes utilisation exp(2^n x) = exp(x)^(2^n) et log2(2^n x) = n + log2 (x) pour avoir un argument proche de zéro (à un pour log) et utiliser une approximation de fonction rationnelle (généralement approximants Padé ). Notez que cette même astuce peut vous obtenir des exponentielles matricielles et des logarithmes. Selon @Stephen Canon, les implémentations modernes favorisent L'expansion de Taylor sur l'approximation rationnelle de la fonction où la division est beaucoup plus lente que la multiplication.
- Les autres fonctions peuvent être déduites de celles-ci. Les mises en œuvre peuvent fournir des routine.
- pow(x, y) = exp(a * log(x)), donc pow est pas pour être utilisé lorsque y est un entier
- hypot(x, y) = abs(x) sqrt(1 + (y/x)^2) si x > y (hypot(y, x) autrement) pour éviter le débordement.
atan2
est calculée avec un appel àsincos
et un peu de logique. Ces fonctions sont les blocs de construction de l'arithmétique complexe. - pour d'autres fonctions transcendantales (gamma, erf, bessel, ...), veuillez consulter l'excellent livre Recettes ou Numérique, 3e édition pour quelques idées. Le good'Old Abramowitz & Stegun {[12] } est également utile. Il y a une nouvelle version à http://dlmf.nist.gov/.
- des Techniques comme l'approximation de Chebyshev, l'expansion continue de la fraction (en fait liée aux approximants Padé) ou l'économie de série de puissance sont utilisées dans des fonctions plus complexes (si vous lisez le code source pour erf, bessel ou gamma par exemple). Je doute qu'ils aient une utilisation réelle dans les fonctions mathématiques simples en métal nu, mais qui sait. Consultez les recettes numériques pour un aperçu.
Chaque implémentation peut être différente, mais vous pouvez consulter une implémentation à partir du code source de la glibc (la bibliothèque GNU C).
Edit: la recherche de code Google a été déconnectée, donc l'ancien lien que j'avais ne va nulle part.
Les sources de la bibliothèque mathématique de la glibc se trouvent ici:
Jetez certainement un oeil aux sources fdlibm. Ils sont gentils parce que la bibliothèque fdlibm est autonome, chaque fonction est bien documentée avec des explications détaillées des mathématiques impliquées, et le code est extrêmement clair à lire.
Ayant beaucoup regardé le code mathématique, je déconseille de regarder la glibc - le code est souvent assez difficile à suivre et dépend beaucoup de la magie de la glibc. La math lib sous FreeBSD est beaucoup plus facile à lire, même si elle est parfois plus lente (mais pas beaucoup).
Pour les fonctions complexes, la principale difficulté est les cas de bordure - la manipulation correcte de nan/inf/0 est déjà difficile pour les fonctions réelles, mais c'est un cauchemar pour les fonctions complexes. La norme C99 définit de nombreux cas d'angle, certains les fonctions ont facilement 10-20 cas de coin. Vous pouvez consulter l'annexe G du document standard C99 à jour pour avoir une idée. Il y a aussi un difficile avec long double, parce que son format n'est pas standardisé - dans mon expérience, vous devriez vous attendre à quelques bugs avec long double. Espérons que la prochaine version révisée de IEEE754 avec une précision étendue améliorera la situation.
La plupart des matériels modernes incluent des unités à virgule flottante qui implémentent ces fonctions de manière très efficace.
Ceux-ci sont presque toujours implémentés en tant qu'appels système. Si vous voulez regarder les sources, vous devez accéder aux sources du système d'exploitation, ce qui signifie que vous devez regarder un système d'exploitation open-source comme Linux ou BSD.