Comment c calcule-t-il sin() et les autres fonctions mathématiques?

j'ai passé en revue les démontages de .NET et le code source de GCC, mais je ne trouve nulle part l'implémentation réelle de sin() et d'autres fonctions mathématiques... ils semblent toujours faire référence à autre chose.

est-ce que quelqu'un peut m'aider à les trouver? Je me sens comme il est peu probable que tout le matériel que C va exécuter sur les fonctions de soutien trig dans le matériel, donc il doit y avoir un algorithme logiciel quelque part , Non?


je suis conscient de plusieurs façons que les fonctions peut être calculé, et ont écrit mes propres routines pour calculer des fonctions en utilisant la série taylor pour le plaisir. Je suis curieux de savoir comment les langages de production réels le font, puisque toutes mes implémentations sont toujours plusieurs ordres de grandeur plus lents, même si je pense que mes algorithmes sont assez intelligents (évidemment, ils ne le sont pas).

210
demandé sur Rakete1111 2010-02-18 01:22:49

20 réponses

dans GNU libm, l'implémentation de sin dépend du système. Par conséquent, vous pouvez trouver l'implémentation, pour chaque plate-forme, quelque part dans le sous-répertoire approprié de sysdeps .

Un répertoire inclut une implémentation en C, fournies par IBM. Depuis octobre 2011, c'est le code qui s'exécute réellement lorsque vous appelez sin() sur un système Linux typique x86-64. Il est apparemment plus rapide que l'assemblage fsin instruction. Code Source: sysdeps/ieee754/dbl-64 / s_sin.c , cherchez __sin (double x) .

ce code est très complexe. Aucun algorithme logiciel n'est aussi rapide que possible et aussi précis sur l'ensemble de la gamme de valeurs x , de sorte que la bibliothèque met en œuvre de nombreux algorithmes différents et sa première tâche est de regarder x et de décider quel algorithme à utiliser. Dans certaines régions, il utilise ce qui ressemble le familier La série de Taylor. Plusieurs algorithmes calculent d'abord un résultat rapide, puis si ce n'est pas assez précis, le jeter et retomber sur un algorithme plus lent.

anciennes versions 32 bits de GCC / glibc utilisé l'instruction fsin , qui est étonnamment inexact pour certaines entrées. Il y a un blog fascinant illustrant ce avec seulement 2 lignes de code .

fdlibm mise en œuvre de sin en C pur est beaucoup plus simple que glibc et est joliment commenté. Code Source: fdlibm / s_sin.c et fdlibm/k_sin.c

178
répondu Jason Orendorff 2014-10-10 15:26:04

OK kiddies, c'est l'heure des pros.... C'est l'une de mes plus grandes plaintes inexpérimenté ingénieurs en logiciel. Ils viennent dans le calcul des fonctions transcendantales à partir de zéro (en utilisant la série de Taylor) comme si personne n'avait jamais fait ces calculs auparavant dans leurs vies. Pas vrai. Il s'agit d'un problème bien défini qui a été abordé des milliers de fois par des ingénieurs logiciels et matériels très intelligents et dont la solution est bien définie. Fondamentalement, la plupart des fonctions transcendantes utilisation Polynômes de tchebychev pour les calculer. Les polynômes utilisés dépendent des circonstances. D'abord, la bible sur cette question est un livre appelé "Computer Approximations" par Hart et Cheney. Dans ce livre, vous pouvez décider si vous avez un adder matériel, un multiplicateur, un diviseur, etc, et décider quelles opérations sont les plus rapides. par exemple, si vous aviez un diviseur vraiment rapide, la façon la plus rapide de calculer sine pourrait être P1(x)/P2(x) où P1, P2 sont des polynômes de Chebyshev. Sans le diviseur rapide, il pourrait être juste P (x), où P a beaucoup plus de termes que P1 ou P2....donc ce serait plus lent. Donc, la première étape est de déterminer votre matériel et ce qu'il peut faire. Ensuite, vous choisissez la combinaison appropriée de polynômes de Chebyshev (est généralement de la forme cos(ax) = aP(x) pour cosinus par exemple, encore une fois où P est un polynôme de Chebyshev). Ensuite, vous décidez quelle précision décimale vous voulez. par exemple, si vous voulez une précision de 7 chiffres, vous cherchez dans le tableau approprié dans le livre que j'ai mentionné, et il vous donnera (pour précision = 7,33) un nombre N = 4 et un nombre polynomial 3502. N est l'ordre du polynôme (donc c'est p4.x ^ 4 + p3.x^3 + p2.x^2 + p1.x + p0), parce que N = 4. Ensuite, vous regardez la valeur réelle des valeurs p4,p3,p2,p1,p0 au dos du livre sous 3502 (elles seront en virgule flottante). Ensuite, vous mettez en œuvre votre algorithme dans le logiciel sous la forme: (((p4.x + p3).x + p2).x + p1).x + p0 ....et c'est comme ça qu'on calcule cosine à 7 décimales sur ce matériel.

Note que la plupart des implémentations matérielles d'opérations transcendantales dans un FPU impliquent généralement un certain microcode et des opérations comme celle-ci (cela dépend du matériel). Les polynômes de Chebyshev sont utilisés pour la plupart des transcendentals mais pas tous. par exemple, la racine carrée est plus rapide pour utiliser une double itération de la méthode de Newton raphson en utilisant d'abord une table de recherche. Encore une fois, ce livre "Computer Approximations" vous le dira.

si vous prévoyez d'implémenter ces fonctions, je recommande à quiconque que recevoir une copie de ce livre. C'est vraiment la bible pour ces types d'algorithmes. Notez qu'il existe des groupes de moyens alternatifs pour calculer ces valeurs comme les cordics, etc, mais ceux-ci ont tendance à être meilleurs pour des algorithmes spécifiques où vous n'avez besoin que d'une faible précision. Pour garantir la précision à chaque fois, les polynômes de chebyshev sont la solution. Comme je l'ai dit, problème bien défini. A été résolu depuis 50 ans maintenant.....et c'est comment il est fait.

Maintenant, cela étant dit, il existe des techniques par lesquelles les polynômes de Chebyshev peuvent être utilisés pour obtenir un résultat de précision unique avec un polynôme de faible degré (comme l'exemple pour cosinus ci-dessus). Ensuite, il existe d'autres techniques pour interpoler entre les valeurs pour augmenter la précision sans avoir à aller à un polynôme beaucoup plus grand, comme "Gal's Accurate Tables Method". Cette dernière technique est celle à laquelle se réfère le post faisant référence à la littérature ACM. Mais en fin de compte, les polynômes de Chebyshev sont ce qui est utilisé pour obtenir 90% du chemin.

de Profiter de.

74
répondu Donald Murray 2013-02-14 07:09:50

fonctions comme sine et cosine sont mis en œuvre dans le microcode à l'intérieur des microprocesseurs. Les puces Intel, par exemple, ont des instructions d'assemblage pour celles-ci. Un compilateur C générera du code qui appelle ces instructions d'assemblage. (Par contre, un compilateur Java ne le fera pas. Java évalue les fonctions trig dans le logiciel plutôt que le matériel, et donc il tourne beaucoup plus lentement.)

puces ne pas utiliser la série Taylor pour calculer les fonctions de trig, au moins pas entièrement. Tout d'abord ils utilisent CORDIC , mais ils peuvent également utiliser une série de Taylor courte pour polir le résultat de CORDIC ou pour des cas spéciaux tels que le calcul sinus avec une haute précision relative pour de très petits angles. Pour plus d'explications, voir cette StackOverflow answer .

62
répondu John D. Cook 2017-05-23 12:18:19

Oui, il y a aussi des algorithmes logiciels pour calculer sin . Fondamentalement, le calcul de ce genre de choses avec un ordinateur numérique est habituellement fait en utilisant méthodes numériques comme approximant le série Taylor représentant la fonction.

méthodes numériques peuvent approximer des fonctions à un montant arbitraire de précision et puisque la quantité de précision que vous avez dans un nombre flottant est fini, ils conviennent ces tâches assez bien.

12
répondu Mehrdad Afshari 2010-02-17 22:25:16

C'est une question complexe. Les processeurs Intel de la famille x86 ont une implémentation matérielle de la fonction sin() , mais ils font partie du FPU X87 et ne sont plus utilisés en mode 64 bits (où les registres SSE2 sont utilisés à la place). Dans ce mode, une implémentation logicielle est utilisée.

il y a plusieurs implémentations de ce genre là-bas. L'un est en fdlibm et est utilisé en Java. Pour autant que je sache, l'implémentation glibc contient des parties de fdlibm, et d'autres pièces fournies par IBM.

implémentations logicielles de fonctions transcendantales telles que sin() utilisent généralement des approximations par polynômes, souvent obtenues à partir de la série Taylor.

11
répondu Thomas Pornin 2010-02-17 22:36:42

utiliser série taylor et essayer de trouver la relation entre les termes de la série afin que vous ne calculez pas les choses encore et encore

voici un exemple pour cosinus:

double cosinus(double x,double prec)
{
    double t , s ;
    int p;
    p = 0;
    s = 1.0;
    t = 1.0;
    while(fabs(t/s) > prec)
    {
        p++;
        t = (-t * x * x) / ((2 * p - 1) * (2 * p));
        s += t;
    }
    return s;}

en utilisant ceci nous pouvons obtenir le nouveau terme de la somme en utilisant celui déjà utilisé (nous évitons le factoriel et x^2p)

explication http://img514.imageshack.us/img514/1959/82098830.jpg

11
répondu Hannoun Yassir 2010-02-17 23:02:47

les polynômes de Chebyshev, comme mentionné dans une autre réponse, sont les polynômes où la plus grande différence entre la fonction et le polynôme est aussi petite que possible. C'est un excellent début.

Dans certains cas, l'erreur maximale est pas ce qui vous intéresse, mais le maximum de l'erreur relative. Par exemple, pour la fonction sine, l'erreur près de x = 0 devrait être beaucoup plus petite que pour les valeurs plus grandes; vous voulez un petit relatif erreur. Ainsi, on calcule le polynôme de Chebyshev pour sin x / x, et on multiplie ce polynôme par X.

ensuite, vous devez trouver comment évaluer le polynôme. Vous voulez l'évaluer de manière à ce que les valeurs intermédiaires soient petites et donc que les erreurs d'arrondissement soient petites. Sinon, les erreurs d'arrondi peuvent devenir beaucoup plus grande que les erreurs dans le polynôme. Et avec des fonctions comme la fonction sinus, si vous êtes négligent, alors il peut être possible que l' résultat que vous calculez pour sin x est plus grand que le résultat pour sin y même si x < Y. Il faut donc choisir avec soin l'ordre de calcul et le calcul des limites supérieures de l'erreur d'arrondissement.

par exemple, sin x = x - x^3/6 + x^5 / 120 - x^7 / 5040... Si vous calculez naïvement sin x = x * (1 - x^2/6 + x^4/120 - x^6/5040...), alors que la fonction entre parenthèses est en baisse, et il se produira que si y est le prochain plus grand nombre à x, alors parfois sin y sera plus petit que sin X. Calculez plutôt sin x = x-x^3 * (1/6-x^2 / 120 + x^4/5040...) où cela ne se fait pas.

pour calculer les polynômes de Chebyshev, vous devez généralement arrondir les coefficients à double précision, par exemple. Mais alors qu'un polynôme de Chebyshev est optimal, le polynôme de Chebyshev avec des coefficients arrondis à la double précision n'est pas le polynôme optimal avec des coefficients de double précision!

Par exemple pour sin (x), où vous avez besoin de coefficients pour x, x^3, x^5, x^7 etc. vous faites ce qui suit: Calculez la meilleure approximation de sin x avec un polynôme (ax + bx^3 + cx^5 + dx^7) avec une précision supérieure à la double, puis arrondissez a à la double précision, donnant A. la différence entre a et a serait assez grande. Calculer maintenant la meilleure approximation de (sin x - Ax) avec un polynôme (b x^3 + cx^5 + dx^7). Vous obtenez des coefficients différents, parce qu'ils s'adaptent à la différence entre a et A. Tour b à double précision B. puis approximatif (sin x-Ax-BX^3) avec un polynôme cx^5 + dx^7 et ainsi de suite. Vous obtiendrez un polynôme qui est presque aussi bon que le polynôme Chebyshev original, mais beaucoup mieux que Chebyshev arrondi à double précision.

ensuite, vous devez tenir compte des erreurs d'arrondissement dans le choix du polynôme. Vous avez trouvé un polynôme avec un minimum d'erreur dans le polynôme en ignorant l'erreur d'arrondi, mais vous voulez optimiser le polynôme plus erreur d'arrondi. Une fois que vous avez le polynôme de Tchebychev, vous pouvez calculer les limites de l'erreur d'arrondi. Dire que f (x) est une fonction P (x) est le polynôme, et E (x) est l'erreur d'arrondi. Vous ne voulez pas optimiser | f (x) - P (x) |, vous souhaitez optimiser | f (x) - P (x) +/- E (x) |. Vous obtiendrez un polynôme légèrement différent qui essaie de maintenir les erreurs polynomiales en bas là où l'erreur d'arrondi est grande, et détend les erreurs polynomiales un peu là où l'erreur d'arrondi est petite.

Tout cela, vous obtiendrez facilement les erreurs d'arrondi au plus 0.55 fois le dernier morceau,+, -,*, / ont des erreurs d'arrondi au plus de 0,50 fois le dernier bit.

10
répondu gnasher729 2015-03-20 16:47:39

pour sin spécifiquement, en utilisant L'expansion de Taylor vous donnerait:

sin (x) := x - x^3/3! + x^5/5! - x^7j / 7! + ... (1)

vous continueriez à ajouter des termes jusqu'à ce que la différence entre eux soit inférieure à un niveau de tolérance accepté ou juste pour un nombre fini d'étapes (plus rapide, mais moins précis). Un exemple serait quelque chose comme:

float sin(float x)
{
  float res=0, pow=x, fact=1;
  for(int i=0; i<5; ++i)
  {
    res+=pow/fact;
    pow*=-1*x*x;
    fact*=(2*(i+1))*(2*(i+1)+1);
  }

  return res;
}

Note: (1) fonctionne en raison de la aproximation sin(x)=x pour les petits angles. Pour des angles plus grands, vous devez calculer de plus en plus de termes pour obtenir des résultats acceptables. Vous pouvez utiliser un argument while et continuer pour une certaine précision:

double sin (double x){
    int i = 1;
    double cur = x;
    double acc = 1;
    double fact= 1;
    double pow = x;
    while (fabs(acc) > .00000001 &&   i < 100){
        fact *= ((2*i)*(2*i+1));
        pow *= -1 * x*x; 
        acc =  pow / fact;
        cur += acc;
        i++;
    }
    return cur;

}
10
répondu Blindy 2017-07-25 19:21:20

la mise en œuvre effective des fonctions de bibliothèque dépend du compilateur et/ou du fournisseur de bibliothèque spécifique. Que ce soit en matériel ou en logiciel, Qu'il s'agisse d'une extension Taylor ou non, etc. vont varier.

je me rends compte que ça ne sert à rien.

6
répondu John Bode 2010-02-17 23:51:55

concernant la fonction trigonométrique telle que sin() , cos() , tan() il n'a pas été fait mention, après 5 ans, d'un aspect important des fonctions de trig de haute qualité: réduction de gamme .

Une première étape dans l'une de ces fonctions est de réduire l'angle en radians, à une distance de 2*π intervalle. Mais π est irrationnel donc des réductions simples comme x = remainder(x, 2*M_PI) introduire l'erreur comme M_PI , ou machine pi, est un rapprochement de π. Alors, comment faire x = remainder(x, 2*π) ?

premières bibliothèques ont utilisé la précision étendue ou la programmation artisanale pour donner des résultats de qualité, mais encore sur une gamme limitée de double . Quand une grande valeur a été demandée comme sin(pow(2,30)) , les résultats étaient dénués de sens ou 0.0 et peut-être avec un indicateur d'erreur fixé à quelque chose comme TLOSS perte totale de précision ou PLOSS perte partielle de précision.

bon intervalle la réduction de grandes valeurs à un intervalle comme-π à π est un problème difficile qui rivalise avec les défis de la fonction trig de base, comme sin() , lui-même.

un bon rapport est réduction D'Argument pour les arguments énormes: bon au dernier bit (1992). Il couvre bien la question: discute le besoin et comment les choses étaient sur diverses plates-formes (SPARC, PC, HP, 30+ autres) et fournit un algorithme de solution donne la qualité résultats pour tous "1519350920 double de -DBL_MAX à DBL_MAX .


si les arguments originaux sont en degrés, mais peuvent être d'une grande valeur, utilisez fmod() en premier pour une meilleure précision. Un bon fmod() introduira aucune erreur et fournira donc une excellente réduction de la portée.

// sin(degrees2radians(x))
sin(degrees2radians(fmod(x, 360.0))); // -360.0 <= fmod(x,360) <= +360.0

diverses identités trig et remquo() offrent encore plus amélioration. Échantillon: sind ()

6
répondu chux 2018-03-26 21:14:35

ils sont généralement implémentés dans un logiciel et n'utiliseront pas le matériel correspondant (c'est-à-dire, aseembly) dans la plupart des cas. Toutefois, comme Jason l'a souligné, ces mesures sont spécifiques à la mise en œuvre.

notez que ces routines logicielles ne font pas partie des sources du compilateur, mais seront plutôt trouvées dans la bibliothèque correspondante telle que clib, ou glibc pour le compilateur GNU. Voir http://www.gnu.org/software/libc/manual/html_mono/libc.html#Trig-Functions

si vous voulez plus de contrôle, vous devez évaluer soigneusement ce dont vous avez besoin exactement. Certaines des méthodes typiques sont l'interpolation des tables de recherche, l'appel d'assemblage (qui est souvent lent), ou d'autres schémas d'approximation tels que Newton-Raphson pour les racines carrées.

5
répondu mnemosyn 2010-02-17 22:32:27

si vous voulez une implémentation en Logiciel, pas en matériel, l'endroit pour chercher une réponse définitive à cette question Est le Chapitre 5 de recettes numériques . Ma copie est dans une boîte, donc je ne peux pas donner de détails, mais la version courte (si je me souviens de cette droite) est que vous prenez tan(theta/2) comme votre opération primitive et calculer les autres à partir de là. Le calcul est fait avec une approximation de série, mais c'est quelque chose qui converge beaucoup plus rapidement qu'un développement en série de Taylor.

Désolé, Je ne peux plus me souvenir sans avoir mis la main sur le livre.

5
répondu Norman Ramsey 2010-02-18 00:34:11

comme de nombreuses personnes l'ont souligné, il dépend de la mise en œuvre. Mais pour autant que je comprenne votre question, vous étiez intéressé par un vrai logiciel implémentation de fonctions mathématiques, mais n'avez tout simplement pas réussi à en trouver une. Si c'est le cas, alors vous êtes ici:

  • télécharger le code source glibc de http://ftp.gnu.org/gnu/glibc /
  • regarder le fichier dosincos.c situé dans racine glibc non emballée \sysdeps\ieee754\DBL-64 dossier
  • de même, vous pouvez trouver des implémentations du reste de la bibliothèque de mathématiques, il suffit de chercher le fichier avec le nom approprié

vous pouvez également avoir un regard sur les fichiers avec l'extension .tbl , leur contenu n'est rien de plus que d'énormes tables de valeurs précalculées de différentes fonctions dans une forme binaire. C'est pourquoi la mise en œuvre est donc rapide: au lieu de calculer tous les coefficients de n'importe quelle série qu'ils utilisent ils font juste une recherche rapide, qui est beaucoup plus rapide. BTW, ils utilisent des séries sur mesure pour calculer sine et cosine.

j'espère que cela aidera.

5
répondu Igor Korkhov 2010-02-18 03:26:19

je vais essayer de répondre pour le cas de sin() dans un programme C, compilé avec le compilateur C de GCC sur un processeur x86 courant (disons un Duo Intel Core 2).

dans la langue C la bibliothèque Standard c inclut des fonctions mathématiques communes, non incluses dans la langue elle-même (par exemple pow , sin et cos pour la puissance, le sinus et le cosinus respectivement). Les en-têtes sont inclus dans math.h .

maintenant sur un système GNU / Linux, ces fonctions de bibliothèques sont fournies par glibc (bibliothèque GNU libc ou GNU C). Mais le compilateur GCC veut que vous liiez à la bibliothèque de mathématiques ( libm.so ) en utilisant le drapeau -lm compilateur pour permettre l'utilisation de ces fonctions mathématiques. Je ne suis pas sûr pourquoi il ne fait pas partie de la bibliothèque standard C. il s'agirait d'une version logicielle des fonctions à virgule flottante, ou"soft-float".

mis à part: la raison pour avoir les fonctions mathématiques séparées est historique, et était simplement destiné à réduire la taille des programmes exécutables dans très Vieux systèmes Unix, peut-être avant que les bibliothèques partagées étaient disponibles, autant que je sache.

maintenant le compilateur peut optimiser la fonction de bibliothèque standard C sin() (fourni par libm.so ) pour être remplacé par un appel à une instruction native à votre CPU/FPU intégré la fonction sin (), qui existe sous forme D'instruction FPU ( FSIN pour x86/x87) sur les nouveaux processeurs comme la série Core 2 (c'est correct à peu près aussi loin que l'i486DX). Cela dépend des options d'optimisation passées au compilateur gcc. Si le compilateur devait écrire du code qui s'exécuterait sur n'importe quel processeur i386 ou plus récent, il ne ferait pas une telle optimisation. Le drapeau -mcpu=486 informerait le compilateur qu'il était sûr d'effectuer une telle optimisation.

maintenant si le programme a exécuté la version logicielle de la fonction sin (), il le ferait sur la base d'un CORDIC (ordinateur numérique de Rotation de coordonnées) ou algorithme BKM , ou plus probablement une table ou le calcul de série de puissance qui est couramment utilisé maintenant pour calculer de telles fonctions transcendantales. [Src: http://en.wikipedia.org/wiki/Cordic#Application]

Any récente (depuis 2,9 x env.) la version de gcc offre également une version intégrée de sin, __builtin_sin() qui sera utilisée pour remplacer l'appel standard à la version de la bibliothèque C, comme une optimisation.

je suis sûr que c'est aussi clair que de la boue, mais avec un peu de chance vous donne plus d'informations que vous ne l'attendiez, et beaucoup de saut de points pour apprendre plus vous-même.

5
répondu mctylr 2017-05-23 10:31:10

il n'y a rien de tel que de frapper la source et de voir comment quelqu'un l'a réellement fait dans une bibliothèque d'usage courant; regardons l'implémentation d'une bibliothèque C en particulier. J'ai choisi uLibC.

Voici la fonction sin:

http://git.uclibc.org/uClibc/tree/libm/s_sin.c

qui semble traiter quelques cas spéciaux, puis effectue une réduction d'argument pour mapper l'entrée à la l'intervalle [-pi/4,pi/4], (fractionnement de l'argument en deux parties, une grande partie et une queue) avant d'appeler la

http://git.uclibc.org/uClibc/tree/libm/k_sin.c

qui fonctionne alors sur ces deux parties. S'il n'y a pas de queue, une réponse approximative est générée à l'aide d'un polynôme du degré 13. S'il y a une queue, vous obtenez une petite addition corrective basée sur le principe que sin(x+y) = sin(x) + sin'(x')y

5
répondu Moschops 2015-07-19 10:21:58

chaque fois qu'une telle fonction est évaluée, alors à un certain niveau il y a très probablement l'un ou l'autre:

  • un tableau de valeurs qui est interpolé (pour des applications rapides et imprécises - p.ex. infographie)
  • l'évaluation d'une série qui converge à la valeur désirée --- probablement pas une série de taylor, plus probablement quelque chose basée sur une quadrature de fantaisie comme Clenshaw-Curtis.

s'il n'y a pas de support matériel, alors le compilateur utilise probablement cette dernière méthode, n'émettant que du code assembleur (sans symboles de débogage), plutôt que d'utiliser une bibliothèque c --- rendant difficile pour vous de suivre le code réel dans votre débogueur.

4
répondu James 2010-02-17 22:41:01

si vous voulez regarder l'implémentation GNU actuelle de ces fonctions en C, consultez le dernier tronc de glibc. Voir la GNU C Library .

3
répondu Chris Tonkinson 2010-02-17 23:56:49

calculer sine/cosine/tangent est en fait très facile à faire à travers le code en utilisant la série Taylor. En écrire un toi-même prend environ 5 secondes.

l'ensemble du processus peut être résumé avec cette équation ici: http://upload.wikimedia.org/math/5/4/6/546ecab719ce73dfb34a7496c942972b.png

voici quelques routines que j'ai écrites pour C:

double _pow(double a, double b) {
    double c = 1;
    for (int i=0; i<b; i++)
        c *= a;
    return c;
}

double _fact(double x) {
    double ret = 1;
    for (int i=1; i<=x; i++) 
        ret *= i;
    return ret;
}

double _sin(double x) {
    double y = x;
    double s = -1;
    for (int i=3; i<=100; i+=2) {
        y+=s*(_pow(x,i)/_fact(i));
        s *= -1;
    }  
    return y;
}
double _cos(double x) {
    double y = 1;
    double s = -1;
    for (int i=2; i<=100; i+=2) {
        y+=s*(_pow(x,i)/_fact(i));
        s *= -1;
    }  
    return y;
}
double _tan(double x) {
     return (_sin(x)/_cos(x));  
}
1
répondu user1432532 2014-04-02 22:07:06

N'utilisez pas la série Taylor. Les polynômes de Chebyshev sont à la fois plus rapides et plus précis, comme l'ont souligné quelques personnes ci-dessus. Voici une implémentation (à l'origine de la ROM ZX Spectrum): https://albertveli.wordpress.com/2015/01/10/zx-sine/

1
répondu Albert Veli 2015-07-18 08:39:57

si vous voulez péché puis asm volatile ("fnis" : "=t"(vsin) : "0"(xrads)); si vous voulez cos puis asm volatile ("fcos" : "=t"(vco) : "0"(xrads)); si vous voulez sqrt alors asm volatile ("fsqrt": "=t "(vsqrt): "0"(valeur)); alors pourquoi utiliser un code inexact alors que les instructions de la machine le feront.

-1
répondu user80998 2015-03-20 15:44:41