Le cosinus du pédant


29

Mon patron m'a juste dit d'écrire une fonction cosinus. Étant un bon connaisseur de mathématiques, mon esprit a immédiatement évoqué la série Taylor appropriée.

cos(x) = 1 / 0! - x^2 / 2! + x^4 / 4! - x^6 / 6! + ... + (-1)^k x^(2k) / (2k)! + ...

Cependant, mon patron est très difficile. Il aimerait pouvoir spécifier exactement le nombre de termes de la série Taylor à calculer. Pouvez-vous m'aider à écrire cette fonction?

Ta tâche

Étant donné une valeur en virgule flottante xde 0à 2 piet un entier positif ninférieur à 100, calculer la somme des premiers ntermes de la série de Taylor donnée ci-dessus pour cos(x).

C'est le , donc le code le plus court l'emporte. L'entrée et la sortie peuvent être prises de n'importe quelle manière standard. Les failles standard sont interdites.

Remarques

  • L'entrée peut être prise sous toute forme raisonnable, tant qu'il existe une séparation claire entre xet n.
  • L'entrée et la sortie doivent être des valeurs à virgule flottante, au moins aussi précises que le calcul de la formule à l'aide de nombres à virgule flottante IEEE simple précision avec une règle d'arrondi standard.
  • Si cela a du sens pour le langage utilisé, les calculs peuvent être effectués en utilisant des quantités rationnelles exactes, mais l'entrée et la sortie doivent toujours être sous forme décimale.

Exemples

 x  |  n | Output
----+----+--------------
0.0 |  1 | 1.0
0.5 |  1 | 1.0
0.5 |  2 | 0.875
0.5 |  4 | 0.87758246...
0.5 |  9 | 0.87758256...
2.0 |  2 | -1.0
2.0 |  5 | -0.4158730...

1
Je suppose que nc'est aussi plus grand que 0?
GamrCorps

8
Je dirais que techniquement ce n'est pas ce que veut dire pédant, mais ce serait trop méta.
PyRulez

8
Si votre patron veut que vous écriviez une bonne fonction ou du moins lisible, vous êtes au mauvais endroit.
Roman Gräf

2
Un patron vraiment pointilleux voudrait calculer le cosinus en utilisant quelque chose d'un peu plus efficace (et précis) que la série Taylor ...
PM 2Ring

6
@ PM2Ring Ce ne serait pas difficile, ce serait raisonnable. La série Taylor est vraiment l'option la plus grossière.
user1997744

Réponses:


64

Operation Flashpoint la langue, 165 157 octets

F={x=_this select 0;n=_this select 1;i=0;r=0;while{i<n*2}do{r=r+x^i/(i call{c=_this;j=c-1;while{j>0}do{c=c*j;j=j-1};if(c<1)then{c=1};c})*(-1)^(i/2);i=i+2};r}

Appeler avec:

hint format["%1\n%2\n%3\n%4\n%5\n%6\n%7",
    [0.0, 1] call f,
    [0.5, 1] call f,
    [0.5, 2] call f,
    [0.5, 4] call f,
    [0.5, 9] call f,
    [2.0, 2] call f,
    [2.0, 5] call f]

Sortie:

enter image description here

L'entrée et la sortie doivent être des valeurs à virgule flottante, au moins aussi précises que le calcul de la formule à l'aide de nombres à virgule flottante IEEE simple précision avec une règle d'arrondi standard.

Je suis assez sûr que les nombres sont des nombres à virgule flottante IEEE simple précision, même si dans la sortie imprimée les décimales plus longues ne sont pas aussi précises. C'est l'impression qui arrondit les chiffres comme ça, en fait les chiffres sont plus précis.

Par exemple, a=1.00001;b=1.000011;hint format["%1\n%2\n%3", a, b, a==b]affichera ceci:

1.00001
1.00001
false

Il est donc clair que la précision réelle des nombres est supérieure à la précision imprimée.



16
@orlp Pourquoi pas?
Steadybox

3
@orlp Je pense que la question la plus appropriée à poser est: pourquoi le langage de script Operation Flashpoint n'est-il pas une variante d' ArnoldC ?
roofcat

2
Hmmm… entrez-vous l'entrée en tirant un nombre donné de tours [n] dans la direction donnée de la boussole [x]? 😍 Opération Flashpoint!
Mormegil

14
@Mormegil Eh bien, généralement non, mais cela peut être fait avec ce morceau de code: dir=-1;num=1;player addEventHandler ["fired", {_dir=getdir (nearestObject [_this select 0, _this select 4]);if (dir < 0) then {dir = _dir} else {if (abs(dir - _dir) < 5) then {num = num + 1} else {hint format["%1", [dir*(pi/180), num] call F];dir=-1;num=1}}}]- La prise de vue dans une direction incrémente le compteur, puis la prise de vue dans une autre direction appelle la fonction cosinus avec la direction précédente et le nombre de prises de vue dans cette direction.
Steadybox

13

05AB1E , 14 11 octets

FIn(NmN·!/O

Essayez-le en ligne!

Explication

F                # for N in [0 ... n] do
 In              # push (x^2)
   (             # negate
    Nm           # raise to the Nth power
      N·!        # push (2*N)!
         /       # divide
          O      # sum

@JamesHolderness: Oui, la langue a subi une refonte assez importante depuis lors. Un bug étrange semble avoir affligé ², mais il peut à la place être remplacé par I.
Emigna

10

MATL , 14 octets

U_iqE:2ep/YpsQ

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication avec exemple

Tous les nombres ont une double précision (c'est la valeur par défaut).

Tenez compte des entrées x = 2.0, n = 5.

U_     % Implicitly input x. Square and negate
       % STACK: -4
iqE    % Input n. Subtract 1, multiply by 2
       % STACK: -4, 8
:      % Range
       % STACK: -4, [1 2 3 4 5 6 7 8]
2e     % Reshape into a 2-row matrix
       % STACK: -4, [1 3 5 7;
       %             2 4 6 8]
p      % Product of each column
       % STACK: -4, [2 12 30 56]
/      % Divide, element-wise
       % STACK: [-2 -0.333333333333333 -0.133333333333333 -0.0714285714285714]
Yp     % Cumulative product of array
       % STACK: [-2 0.666666666666667 -0.0888888888888889 0.00634920634920635]
s      % Sum of array
       % STACK: -1.41587301587302
Q      % Add 1. Implicitly display
       % STACK: -0.41587301587302

10

Mathematica, 49 41 39 31 octets

Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]&

Ancienne version plus "fun": (39 octets)

Normal@Series[Cos@k,{k,0,2#2-2}]/.k->#&

10 octets enregistrés grâce à @Pavel et 8 grâce à @Greg Martin!


9
Bien que la Seriescapacité de Mathematica soit en effet impressionnante et amusante, il s'avère que l'implémentation manuelle Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]&est plus courte ici.
Greg Martin

9

Gelée , 12 11 octets

ḶḤµ⁹*÷!_2/S

Essayez-le en ligne!

Comment?

ḶḤµ⁹*÷!_2/S - Main link: n, x           e.g. 5, 2.0
Ḷ           - lowered range(n)              [0,1,2,3,4]
 Ḥ          - double (vectorises)           [0,2,4,6,8]
  µ         - monadic chain separation (call that i)
   ⁹        - link's right argument         2.0
    *       - exponentiate(i) (vectorises)  [1.0,4.0,16.0,64.0,256.0]
      !     - factorial(i) (vectorises)     [1,  2,  24,  720, 40320]
     ÷      - divide (vectorises)           [1.0,2.0,0.6666666666666666,0.08888888888888889,0.006349206349206349]
        2/  - pairwise reduce by:
       _    -     subtraction               [-1.0,0.5777777777777777,0.006349206349206349]
         S  - sum                           -0.41587301587301617

8

Gelée, 22 octets

-*ð×ø⁹*⁸²ð÷ø⁸Ḥ!
⁸R’Ç€S

Il s'agit d'un programme complet qui prend n comme premier argument et x comme second.

Explication:

              Creates a function to compute each term in the series. 
Its argument we will call k, eg k=3 computes 3rd term. Take x=2 for example.
-*           Computes (-1)^k. Eg -1
ð×ø        Multiplies by the quantity of
⁹             x.  
*             to the power of
⁸             k
²             ...squared. Eg -1 × (2³)² 
ð÷ø        divides by the quantity of
⁸              k
Ḥ             doubled
!               ...factorial. Eg -1 × (2³)²/(6!).


                Main link, first argument n and second argument n. Eg n=4, x=2.
⁸R            Creates range(n). Eg [1,2,3,4]
’                Decrements each element. Eg [0,1,2,3]
Ç€            Maps the above function over each element. Eg [1,-2,0.666,-0.0889]
S               Sum all all of the elements.  Eg -0.422.

7
Bienvenue chez PPCG!
Martin Ender

6

Python, 54 octets

f=lambda x,n,t=1,p=1:n and t+f(x,n-1,-t*x*x/p/-~p,p+2)

Si vous utilisez Python 2, assurez-vous de passer x comme un flottant, pas un entier, mais je crois comprendre que peu importe si vous utilisez Python 3.


5

TI-Basic, 41 40 octets

Prompt X,N
sum(seq((-(X+1E-49)2)^Q/((2Q)!),Q,0,N-1
1E-49 est ajouté à l'angle car TI-Basic renvoie une erreur pour 0 ^ 0, il est juste assez grand pour ne pas provoquer l'erreur et il n'est pas assez grand pour changer la réponse.


4

C, 96 octets

Récursif en direct

f(n){return n?n*f(n-1):1;}float c(n,x)float x;{return n?c(n-1,x)+pow(-1,n)*pow(x,2*n)/f(2*n):1;}

Détaillé

f(n) // factorial(n)
{
    return n ?   // n != 0 ?
        n*f(n-1) // n! = n * (n-1)!
    : 1;         // 0! = 1
}

float c(n,x)float x; // cos(x) with n+1 terms
{
    return n ?        // n != 0 ?
        c(n-1, x)     // cos(x) (n-1)th term
        + pow(-1, n)  // + (-1)^n
        * pow(x, 2*n) // * x^(2n)
        / f(2 * n)    // / (2n)!
    : 1;              // cos(x) at n=0
}

Progressive Recursive, 133 bytes Live

#define F float
#define c(x,n) 1+g(1,n,x,1,1,1)
F g(F i,F n,F x,F s,F p,F f){s=-s;p*=x*x;f*=i;return i<n?g(i+1,n,x,s,p,f)+s/2*p/f:0;}

Détaillé

#define F float // shorthand float

#define c(x,n) 1+g(1,n,x,1,1,1) // macro function

F g(F i,F n,F x,F s,F p,F f)
{
    s = -s;   // (-1)^n = (-1) * (-1)^(n-1)
    p *= x*x; // x^(2n) =  x^2 * x^(2(n-1))
    f *= i;   //    2n! =    2 * (1*2*..*n)

    return i < n ?       // i = 0 .. n-1
        g(i+1,n,x,s,p,f) // next term
        + s / 2 * p / f  // s*p/2f = s/2*p/f
        : 0;             // don't compute nth term
}

Version 96b c(0.5, 80)=> NaN, pour débordementf(80)=0
l4m2

Les fonctions récursives de @ l4m2 sont là pour jouer au golf, mais elles ne sont pas pratiques car elles peuvent facilement déborder car le nombre d'appels dépasse la limite de la pile d'appels, et même avec des limites plus élevées, c'est un gaspillage de ressources, pour la solution ci-dessus essayez petits nombres.
Khaled.K

1
Problème dire directement n<100donc vous au moins n'allez pas aussi loin dans la gamme. Pas de débordement de pile
l4m2

Si le problème se pose n<100et que vous utilisez la O(2^n)solution, je suppose que ça va, tant que cela retoune finalement le résultat
l4m2

1
Pour info, le résultat NaN n'a rien à voir avec la récursivité - c'est un débordement du calcul factoriel qui utilise des entiers alors qu'il devrait utiliser des flottants (198! Ne va jamais tenir dans un int).
James Holderness

4

JavaScript (ES6), 46 octets

f=
x=>g=(n,t=1,p=0)=>n&&t+g(--n,-t*x*x/++p/++p,p)
<div oninput=o.textContent=f(x.value)(n.value)><input id=x><input type=number min=1 value=1 id=n><pre id=o>1

Prend les entrées au curry (x) (n).


Pourquoi ne pas en faire un extrait?
Arjun

4

C, 71 octets

en utilisant le schéma Horner

float f(n,x)float x;{float y;for(n+=n;n;)y=1-(y*x*x/n--)/n--;return y;}

Version non golfée:

float f(n,x) float x;
{
  float y = 0.0;
  for(n = 2*n; n>0; n -= 2)
  {
    y = 1-y*x*x/n/(n-1);
  }
  return y;
}

Sur quelle plateforme cela fonctionne-t-il?
anatolyg

4

R, 70 64 octets

function(x,n)sum(sapply(1:n-1,function(y)(-x^2)^y/gamma(2*y+1)))

sauvé 6 octets grâce à la réponse de pizzapants184 avec l'astuce (-x ^ 2) ^ y

65 octets:

function(x,n)Reduce(function(a,b)a+(-x^2)^b/gamma(2*b+1),1:n-1,0)

à peu près la mise en œuvre naïve de cela, mais un peu de golf; renvoie une fonction anonyme qui calcule la série Taylor au n spécifié

  • l'utilisation d'une réduction prend un octet de plus, car initelle doit être définie sur 0
  • utilise gamma(n+1)au lieu defactorial(n)
  • 1:n-1 est équivalent à 0:(n-1)

3

oK , 38 octets

Cela fonctionne également en k , mais prend 39 octets car il 'faut écrire comme à la /:place (au moins, dans kmac 2016.06.28 c'est le cas).

{+/(y#1 -1)*{(*/y#x)%*/1+!y}.'x,'2*!y}

Explication:

Commençons par le bit du milieu. (*/y#x)est l'exponentiation, elle est équivalente à x^y. */1+!yserait y!, ou yfactorielle. %est la division. Par conséquent, la fonction au milieu est middle(x,y) = (x^y)/(y!).

Maintenant, le bit à droite, auquel la fonction ci-dessus est appliquée. 2*!yest {0, 2, 4, ..., 2*(y-1)}. x,'ajoute xà chaque élément de cette liste, le transformant en {(x, 0), (x, 2), (x, 4), ..., (x, 2*(y-1))}. Le .'s'applique alors middleà chaque paire de nombres ( map, essentiellement).

Enfin, (y#1 -1)*multiplie le résultat par 1 ou -1 (en alternance) et +/prend la somme.


3

Haskell, 71 octets

f x n=sum$map(\i->(-1)^i*x^(2*i)/fromIntegral(product[1..2*i]))[0..n-1]

C'est une réponse assez ennuyeuse qui n'est pas trop difficile à déchiffrer. Les fromIntegralpiqûres vraiment, cependant. (L' /opérateur requiert des opérandes du même type numérique dans Haskell, et la coercition entre les types numériques n'est pas autorisée sans une fonction verbeuse.)


1
Une compréhension de la liste peut vous faire économiser quelques bouchées:f x n=sum[(-1)^i*x^(2*i)/fromIntegral(product[1..2*i])|i<-[0..n-1]]
Julian Wolf

1
Bienvenue au golf PPCG et Haskell en particulier!
Laikoni

3

Gelée , 12 octets

²N*Ḷ}©÷®Ḥ!¤S

Essayez-le en ligne!

Comment ça marche

²N*Ḷ}©÷®Ḥ!¤S  Main link. Left argument: x. Right argument: n

²             Square; yield x².
 N            Negate; yield -x².
     ©         Call the link to the left and copy the result to the register.
   Ḷ}          Call unlength on the right argument, yielding [0, 1, ..., n-1].
  *           Yield [1, -x², ..., (-x²)**(n-1)].
          ¤   Combine the three links to the left into a niladic chain.
       ®        Yield the value in the register, [0, 1, ..., n-1].
        Ḥ       Unhalve; yield [0, 2, ..., 2n-2].
         !      Factorial; yield [0!, 2!, ..., (2n-2)!].
      ÷         Division; yield [1/0!, -x²/2!, ..., (-x²)**(n-1)/(2n-2)!].
           S  Take the sum.


3

Haskell , 61 octets

x#n=sum[(-1*x^2)^i/fromIntegral(product[1..2*i])|i<-[0..n-1]]

Cela semblait suffisamment différent de l'autre solution Haskell pour justifier une réponse distincte. La mise en œuvre devrait être assez explicite - appelez avec x#nxest le nombre dont le cosinus doit être calculé et nl'ordre de la somme partielle à prendre.


Vous pouvez économiser plusieurs octets en supprimant fromIntegralet en utilisant **à la place de ^, comme celui- ci
B. Mehta

x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]]enregistre 3 octets supplémentaires.
Lynn

3

Pyt , 37 34 33 octets

←←ĐĐ↔3Ș1~⇹ř⁻^04Ș⇹ř⁻^²*0↔ř⁻2*!+/+Ʃ

3

J, 26 24 octets

+/@:(!@]%~^*_1^2%~])2*i.

-2 octets grâce à @cole

À l'origine, j'avais prévu d'utiliser un gérondif cyclique pour alterner entre l'ajout et la soustraction, mais je n'ai pas pu le faire fonctionner.

Explication:

                    2*i.     | Integers from 0 to 2(n-1)
    (              )         | Dyadic train:
            _1^-:@]          | -1 to the power of the left argument
          ^*                 | Times left arg to the power of right arg
     !@]%~                   | Divided by the factorial of the right arg
+/@:                         | Sum

1
24 octets: +/@:(!@]%~^*_1^2%~])2*i.Je vais enquêter sur un gérondif cyclique: il a probablement échoué car J évalue de /droite à gauche, vous devez donc l'utiliser |.(ou peut-être avez-vous expliqué cela et avez-vous toujours eu des difficultés).
cole

3

Perl 6 , 53 octets

{(sum (1,*i*$^x...*)[^2*$^n] »/»(1,|[\*] 1..*)).re}

Essayez-le en ligne!

Cela calcule en fait l'exponentielle complexe e pour le double du nombre de termes demandés, puis prend la partie réelle.


2

MATLAB avec Symbolic Math Toolbox, 57 octets

@(x,n)eval(subs(taylor(sym('cos(x)'),'Order',2*n),'x',x))

Ceci définit une fonction anonyme qui prend avec des doubleentrées x, net renvoie le résultat comme double.

Exemple (testé sur R2015b):

>> @(x,n)eval(subs(taylor(sym('cos(x)'),'Order',2*n),'x',x))
ans = 
    @(x,n)eval(subs(taylor(sym('cos(x)'),'Order',2*n),'x',x))
>> f = ans; format long; f(0,1), f(0.5,1), f(0.5,2), f(0.5,4), f(0.5,9), f(2,2), f(2,5)
ans =
     1
ans =
     1
ans =
   0.875000000000000
ans =
   0.877582465277778
ans =
   0.877582561890373
ans =
    -1
ans =
  -0.415873015873016

2

JavaScript ES7 60 octets

x=>a=n=>--n?(-1)**n*x**(2*n)/(f=m=>m?m*f(m-1):1)(2*n)+a(n):1


x=>a=n=>                                                         // Curry-d function, it basically returns another function
        --n?                                              :1  // subtract one from n. If n - 1 is 0, return 1
            (-1)**n*                                             // This generates the sign of the number
                    x**(2*n)/                                    // This creates the part before the division, basicaly x^2n
                             (f=m=>m?m*f(m-1):1)(2*n)            // This creates a recursive factorial function and calls it with 2n
                                                     +a(n)    // Recursively call the function. This adds the elements of the taylor series together

Pour l'utiliser:

Appuyez sur F12, saisissez la fonction, puis faites

c(x)(n)

2

C 144 130 octets

F(m){int u=1;while(m)u*=m--;return u;}float f(float x,n){float s;for(int i=1;i<n;i++)s+=pow(-1,i)*pow(x,2*i)/(F(2*i));return 1+s;}

Version non golfée:

//Function to calculate factorial
int F(int m)
{
  int u=1;

  while(m>1)
   u*=m--; 

  return u;
}

//actual function called in main function   
float f(float x, int n)
{

  float s=0.0;

  for(int i=1;i<=n-1;i++)
     s+=pow(-1,i)*pow(x,2*i)/(F(2*i)); 

  return 1+s;
 }

Merci Kevin d'avoir économisé quelques octets!


Vous pouvez économiser quelques octets en massant les définitions de fonction:F(m){...}f(x,n)float x;{...}
Kevin

Puisque u * 1 == u, vous pouvez faire la boucle dans la première fonction soit while(m)u*=m--ou u=m;while(--m)u*=m(même longueur)
Kevin

i<=n-1est le même quei<n
Kevin

@Kevin Merci, vous avez absolument raison, vous n'avez pas joué au golf depuis un certain temps maintenant. :)
Abel Tom



2

Stax , 12 octets

ü┘·.ⁿYeò≥Vîû

Exécuter et déboguer

Déballé, non golfé et commenté, il ressemble à ceci.

            Input is `x n`
Z           Push a zero underneath the top.  The stack is now `x 0 n` 
D           Run the rest of the program n times.
  xJNi|*    (-x*x)^i where i is the iteration index
  iH|F/     divide that by factorial(2i)
  +         add to the running total so far
            final result is implicitly printed

Exécutez celui-ci



1

PHP, 76 octets

for($f=1;$i<$argv[2]*2;$f*=++$i)$i&1?:$s+=(-1)**$k++*$argv[1]**$i/$f;echo$s;

prend Xet Ndes arguments de ligne de commande; courir avec -r.

boucle $ide 0à N*2-1, prise fac($i)en $f; si $iest pair, ajoutez le terme à la somme $s. imprimer la somme.


J'aimerais avoir des nombres complexes (avec M_Icomme unité imaginaire);
Je voudrais simplement multiplier $favec M_I*++$iet enregistrer 7 octets.

Peut-être que Mathematica peut le faire. Mais Mathematica n'est pas obligé.

Je pourrais enregistrer deux octets avec cos(M_PI*$i/2)au lieu de $i&1?:et (-1)**$k++;
mais il serait un peu étrange d'utiliser un cosinus intégré pour construire une fonction cosinus.


1

Axiome, 36 octets

g(a,n)==eval(taylor(cos(x)),a).(2*n)

Construisez l'infini (au sens fini mais on peut demander de construire la liste des 2 * n éléments si le PC a assez de mémoire) liste des sommes partielles pour la série Taylor pour cos (x) calculer en 'a', en "eval ( taylor (cos (x)), a) "; obtient l'élément 2 * n de cette liste dans ". (2 * n)". Cas de test:

(47) -> g(0,1)
   (47)  1
                                                 Type: Expression Integer
(48) -> g(0.5,1)
   (48)  1.0
                                                   Type: Expression Float
(49) -> g(0.5,2)
   (49)  0.875
                                                   Type: Expression Float
(50) -> g(0.5,4)
   (50)  0.8775824652 7777777778
                                                   Type: Expression Float
(51) -> g(0.5,9)
   (51)  0.8775825618 9037271611
                                                   Type: Expression Float
(52) -> g(2.0,5)
   (52)  - 0.4158730158 7301587302
                                                   Type: Expression Float
(53) -> g(2.0,800)
   (53)  - 0.4161468365 471423870

1

J , 17 octets

4 :'2&o.T.(+:y)x'

Essayez-le en ligne!

Utilise un intégré , qui je suppose est OK.

Malheureusement, je ne sais pas vraiment comment bien travailler avec des fonctions qui prennent des arguments via un curry comme celui-ci, j'ai donc dû le faire explicitement. Je suis sûr qu'il existe un moyen de le faire tacitement ou plus court.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.