self made pow() en c++
Je lisais Comment puis-je écrire une fonction de puissance moi-même? et la réponse donnée par dan04 a attiré mon attention parce que je ne suis pas sûr de la réponse donnée par le fortran, mais je l'ai pris et mis en œuvre cette:
#include <iostream>
using namespace std;
float pow(float base, float ex){
//power of 0
if (ex == 0){
return 1;
//negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
//even exponenet
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main(){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ".5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ",2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ",3) = " << pow(ii, 3) << endl;
}
}
si je ne suis pas sûr si j'ai traduit ce droit, car tous les appels donnant 5. l'exposant de retour 0. Dans la réponse, il indique qu'il pourrait avoir besoin d'une log2(x) basé sur a^b = 2^(b * log2(a))
, mais je suis pas sûr à propos de mettre la que dans que je ne sais pas où le mettre, ou si je suis à même de penser à ce droit.
NOTE: je sais que cela pourrait être définies dans une bibliothèque de mathématiques, mais je n'ai pas besoin de tous les frais supplémentaires de toute une bibliothèque de mathématiques pour quelques fonctions.
EDIT: est-ce que quelqu'un sait a floating-point de la mise en œuvre pour l'exposant fractionnaire? (J'ai vu une double mise en œuvre, mais qui a été à l'aide d'un truc avec les registres, et j'ai besoin de virgule flottante, et l'ajout d'une bibliothèque, il suffit de faire un truc, je serais mieux juste, y compris la bibliothèque de mathématiques)
il vous manque la fraction de l'exposant (le code, il existe pour un même exposant) - en regardant le lien d'origine, je pense que vous copiez à partir de quelque chose qui ne prend en charge que des exposants entiers (d'où les tests pour les fractions de échouera).
Je vous assure que c'est plus cher que les mathématiques.h pow.
dang. pourriez-vous m'aider en montrant les changements nécessaires
c'est log2(n) n'est-ce pas? donc, pour pow(base, 1000000) c'est une profondeur d'environ 20.
OriginalL'auteur gardian06 | 2012-03-11
Vous devez vous connecter pour publier un commentaire.
Ci-dessous sont des liens vers les mises en production de powf.
J'attends des solutions plus simples de l'absence de précision dans le résultat ou pas manipuler InF et NaN paramètres.
http://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/expf_logf_powf.c
http://opensource.apple.com/source/Libm/Libm-315/Source/ARM/powf.c
float
, évite.C'est un bijou ive été la recherche pour le passé 3 semaines!!!! Merci de poster!
Je sais que ce genre de posts sont de courte durée, mais mon plus grand merci pour votre contribution! Cela a rendu mon travail beaucoup plus facile.
OriginalL'auteur Brian Swift
J'ai regardé ce papier ici qui décrit comment rapprocher la fonction exponentielle pour la double précision. Après une petite recherche sur Wikipédia à propos de simple précision à virgule flottante représentation j'ai travaillé l'équivalent d'algorithmes. Ils ont seulement mis en œuvre la fonction exp, donc j'ai trouvé une fonction inverse pour le journal et puis tout simplement ne
la compilation de ce gcc4.6.2 donne une fonction pow près de 4 fois plus rapide que le standard de la bibliothèque de la mise en œuvre (compilation avec O2).
Remarque: le code de l'EXP est repris presque mot pour mot à partir de l'étude que j'ai lue et la fonction LOG est copié à partir de ici.
Voici le code correspondant:
Il y a encore quelques optimisation que vous pouvez faire ici, ou peut-être que ce est assez bon.
C'est une approximation, mais si vous avez été satisfait avec les erreurs introduites à l'aide de la double représentation, j'imagine que ce sera satisfaisant.
OriginalL'auteur SirGuy
Je pense que vous pourriez essayer de le résoudre en utilisant les séries de Taylor,
cochez cette.
http://en.wikipedia.org/wiki/Taylor_series
Avec les séries de Taylor vous pouvez résoudre tout difficile à résoudre calcul tels que 3^3.8 en utilisant le déjà connu des résultats, tels que 3^4. Dans ce cas, vous avez
3^4 = 81 donc
3^3.8 = 81 + 3.8*3( 3.8 - 4) +..+.. et ainsi de suite dépend de combien grande est votre n, vous obtiendrez la plus proche de la solution de votre problème.
Vous pouvez comparer le résultat du dernier calcul de la série avec un certain nombre standard comme 0.0000001 donc, c'est une limite de la précision. Donc, vous devez faire comme itération comme une somme et vérifier le calcul de chaque itération si la valeur finale de c'est < que 0.000001 par exemple, vous aurez le seuil de l'itération.
La série de Taylor est seulement approximative en un seul point, où, comme un minimax algorithme tel que (tchebychev, remez) sont à plus d'un bond, qui donne optimale équi-ondulation d'erreur.
OriginalL'auteur AlexTheo
Je pense que l'algorithme que vous cherchez peut être"racine nième'. Avec une estimation initiale de 1 (pour k == 0):
test:
.3
J'ai essayé d'ajouter .3, semble fonctionner (je suis en utilisant GCC 4.5). mais voir le modifier pour le base == 0...
J'ai essayé d'ajouter 1/3 de l'exposant, les valeurs sont incompréhensibles, je vais le tester plus...
Avez-vous littéralement essayer
1/3
? Parce que c'est 0 en raison de la division entière. Pour faire flotter à la division, vous avez besoin d'utiliser1./3.
à la place (en fait l'un des points c'est déjà suffisant).J'ai essayé avec flotteur, mais la démarche est fondamentalement vicié, perdre la précision de la conversion d'entier effectuée par 1/ex à nth_root(de base, 1/ex);
OriginalL'auteur CapelliC
Moi et mon ami étaient confrontés au même problème que nous, nous sommes sur un OpenGL projet et en mathématiques.h ne suffit pas dans certains cas. Notre instructeur a aussi eu le même problème et il nous a dit de nous séparer d'alimentation en entier et flottant pièces. Par exemple, si vous êtes à calculer x^11.5 vous pouvez calculer sqrt(x^115, 10) qui peut entraîner un résultat plus précis.
OriginalL'auteur Cihad Turhan