El coseno del pedante

29

Mi jefe me acaba de decir que escriba una función coseno. Siendo un buen geek matemático, mi mente inmediatamente evocó la serie Taylor adecuada.

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

Sin embargo, mi jefe es muy exigente. Le gustaría poder especificar exactamente cuántos términos de la serie Taylor calcular. ¿Me pueden ayudar a escribir esta función?

Tu tarea

Dado un valor de punto flotante xde 0a 2 piy un número entero positivo nde menos de 100, calcular la suma de los primeros ntérminos de la serie de Taylor dados anteriormente para cos(x).

Este es el , por lo que gana el código más corto. La entrada y la salida se pueden tomar de cualquiera de las formas estándar. Las lagunas estándar están prohibidas.

Notas

  • La entrada puede tomarse en cualquier forma razonable, siempre que haya una separación clara entre xy n.
  • La entrada y la salida deben ser valores de punto flotante, al menos tan precisos como calcular la fórmula utilizando números de punto flotante IEEE de precisión simple con alguna regla de redondeo estándar.
  • Si tiene sentido para el lenguaje que se está utilizando, los cálculos se pueden hacer usando cantidades racionales exactas, pero la entrada y la salida todavía estarán en forma decimal.

Ejemplos

 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...
Silvio Mayolo
fuente
1
Supongo que ntambién es mayor que 0?
GamrCorps
8
Diría que técnicamente no es lo que significa pedante, pero eso sería demasiado meta.
PyRulez
8
Si su jefe quiere que escriba una función buena o al menos legible, está en el lugar equivocado.
Roman Gräf
2
Un verdadero jefe exigente querría coseno calcular el uso de algo un poco más eficiente (y exacta) de la serie de Taylor ...
PM 2Ring
66
@ PM2Ring Eso no sería exigente, sería razonable. La serie Taylor es realmente la opción más cruda.
user1997744

Respuestas:

64

Operation Flashpoint lenguaje de script, 165 157 bytes

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}

Llamar con:

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]

Salida:

ingrese la descripción de la imagen aquí

La entrada y la salida deben ser valores de punto flotante, al menos tan precisos como calcular la fórmula utilizando números de punto flotante IEEE de precisión simple con alguna regla de redondeo estándar.

Estoy bastante seguro de que los números son números de coma flotante IEEE de precisión simple, aunque en la salida impresa los decimales más largos no son tan precisos. Es la impresión que redondea los números así, en realidad los números son más precisos.

Por ejemplo, a=1.00001;b=1.000011;hint format["%1\n%2\n%3", a, b, a==b]generará esto:

1.00001
1.00001
false

Claramente, la precisión real de los números es mayor que la precisión impresa.

Steadybox
fuente
16
@orlp ¿Por qué no?
Steadybox
3
@orlp Creo que la pregunta más apropiada es: ¿por qué el lenguaje de scripts Operation Flashpoint no es una variante de ArnoldC ?
ceilingcat
2
Hmmm ... ¿ingresas la entrada disparando un número dado de rondas [n] a la dirección de la brújula [x]? 😍 ¡Operación Flashpoint!
Mormegil
14
@Mormegil Bueno, generalmente no, pero eso se puede hacer con este código: 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}}}]- Disparar en alguna dirección incrementa el contador, y luego disparar en otra dirección llama a la función coseno con la dirección anterior y el número de disparos en esa dirección.
Steadybox
13

05AB1E , 14 11 bytes

FIn(NmN·!/O

Pruébalo en línea!

Explicación

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
Emigna
fuente
@JamesHolderness: Sí, el lenguaje ha pasado por una revisión bastante importante desde entonces. Un error extraño parece haber afectado ², pero en su lugar puede ser reemplazado por I.
Emigna
10

MATL , 14 bytes

U_iqE:2ep/YpsQ

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación con ejemplo

Todos los números tienen doble precisión (este es el valor predeterminado).

Considere insumos 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
Luis Mendo
fuente
10

Mathematica, 49 41 39 31 bytes

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

Versión antigua y más "divertida": (39 bytes)

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

¡Ahorré 10 bytes gracias a @Pavel y 8 gracias a @Greg Martin!

GamrCorps
fuente
99
Si bien la Seriescapacidad de Mathematica es realmente increíble y divertida, resulta que la implementación manual Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]&es más corta aquí.
Greg Martin
9

Jalea , 12 11 bytes

ḶḤµ⁹*÷!_2/S

Pruébalo en línea!

¿Cómo?

ḶḤµ⁹*÷!_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
Jonathan Allan
fuente
8

Jalea, 22 bytes

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

Este es un programa completo que toma n como el primer argumento yx como el segundo.

Explicación:

              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.
fireflame241
fuente
77
Bienvenido a PPCG!
Martin Ender
6

Python, 54 bytes

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

Si usa Python 2, asegúrese de pasar x como flotante, no como entero, pero entiendo que no importa si está usando Python 3.

Neil
fuente
5

TI-Basic, 41 40 bytes

Prompt X,N
sum(seq((-(X+1E-49)2)^Q/((2Q)!),Q,0,N-1
1E-49 se agrega al ángulo porque TI-Basic arroja un error para 0 ^ 0, es lo suficientemente grande como para no causar el error y no es lo suficientemente grande como para cambiar la respuesta.

pizzapants184
fuente
4

C, 96 bytes

Recursive Live

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

Detallado

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
}

Recursivo progresivo, 133 bytes en vivo

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

Detallado

#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
}
Khaled.K
fuente
96b versión c(0.5, 80)=> NaN, para desbordamientof(80)=0
l4m2
Las funciones recursivas de @ l4m2 están aquí con el propósito de jugar al golf, pero no son prácticas, ya que pueden desbordarse fácilmente ya que el número de llamadas excede el límite de la pila de llamadas, e incluso con límites más altos es un desperdicio de recursos, para la solución anterior, intente números más pequeños
Khaled.K
1
El problema dice directamente, n<100así que al menos no vas tan lejos en el rango. No desbordamiento de pila
l4m2
Si el problema dice n<100y usa la O(2^n)solución, supongo que está bien, siempre y cuando eventualmente vuelva a generar el resultado
l4m2 el
1
Para su información, el resultado de NaN no tiene nada que ver con la recursividad: es un desbordamiento del cálculo factorial que usa números enteros cuando debería usar flotantes (¡198! Nunca encajará en un int).
James Holderness
4

JavaScript (ES6), 46 bytes

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

Toma entradas al curry (x) (n).

Neil
fuente
¿Por qué no convertirlo en un fragmento?
Arjun
4

C, 71 bytes

utilizando el esquema de Horner

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

Versión sin golf:

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;
}
Hagen von Eitzen
fuente
¿En qué plataforma funciona esto?
anatolyg
4

R, 70 64 bytes

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

ahorró 6 bytes gracias a la respuesta de pizzapants184 con el truco (-x ^ 2) ^ y

65 bytes:

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

más o menos la implementación ingenua de esto, pero un poco de golf; devuelve una función anónima que calcula la serie Taylor al n especificado

  • el uso de Reducir toma un byte más, ya initque debe establecerse en 0
  • utiliza en gamma(n+1)lugar defactorial(n)
  • 1:n-1 es equivalente a 0:(n-1)
Giuseppe
fuente
3

ok , 38 bytes

Esto también funciona en k , pero toma 39 bytes porque uno 'debe escribirse como en su /:lugar (al menos, en kmac 2016.06.28 lo hace).

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

Explicación:

Comencemos con el bit del medio. (*/y#x)es exponenciación, es equivalente a x^y. */1+!ysería y!, o yfactorial. %es división Por lo tanto, la función en el medio es middle(x,y) = (x^y)/(y!).

Ahora el bit de la derecha, al que se aplica la función anterior. 2*!yes {0, 2, 4, ..., 2*(y-1)}. x,'antecede xa cada elemento de esa lista, convirtiéndolo en {(x, 0), (x, 2), (x, 4), ..., (x, 2*(y-1))}. El .'entonces se aplica middlea cada par de números ( map, esencialmente).

Finalmente, (y#1 -1)*multiplica el resultado por 1 o -1 (alternando), y +/toma la suma.

zgrep
fuente
3

Haskell, 71 bytes

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

Esta es una respuesta bastante aburrida que no es demasiado difícil de descifrar. La fromIntegralrealidad del momento, sin embargo. (El /operador requiere operandos del mismo tipo numérico en Haskell, y la coerción entre tipos numéricos no está permitida sin una función verbal).

Enderperson1010
fuente
1
Una comprensión de la lista puede ahorrarle algunas picaduras:f x n=sum[(-1)^i*x^(2*i)/fromIntegral(product[1..2*i])|i<-[0..n-1]]
Julian Wolf
1
¡Bienvenido a PPCG y al golf Haskell en particular!
Laikoni
3

Jalea , 12 bytes

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

Pruébalo en línea!

Cómo funciona

²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.
Dennis
fuente
3

Haskell , 61 bytes

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

Esto parecía lo suficientemente diferente de la otra solución de Haskell para garantizar una respuesta por separado. La implementación debe explicarse por sí misma: llame con x#ndónde xestá el número cuyo coseno se calculará y nel orden de la suma parcial que se tomará.

Julian Wolf
fuente
Puede guardar bastantes bytes quitando fromIntegraly usando **en lugar de ^, como este
B. Mehta
x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]]ahorra 3 bytes más.
Lynn
3

Pyt , 37 34 33 bytes

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

J, 26 24 bytes

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

-2 bytes gracias a @cole

Originalmente planeé usar un gerundio cíclico para alternar entre sumar y restar, pero no pude hacerlo funcionar.

Explicación:

                    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
Bolce Bussiere
fuente
1
24 bytes: +/@:(!@]%~^*_1^2%~])2*i.Voy a investigar un gerundio cíclico: probablemente falló, ya que J evalúa de /derecha a izquierda, por lo que debe usarlo |.(o tal vez lo tuvo en cuenta y aún tuvo dificultades).
cole
3

Perl 6 , 53 bytes

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

Pruébalo en línea!

Esto realmente calcula el exponencial complejo e para el doble del número de términos solicitados y luego toma la parte real.

Sean
fuente
2

MATLAB con Symbolic Math Toolbox, 57 bytes

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

Esto define una función anónima con que se lleva a doublelas entradas x, ny emite el resultado como una double.

Ejemplo (probado en 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
Luis Mendo
fuente
2

JavaScript ES7 60 bytes

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

Para usarlo:

Presione F12, escriba la función y luego haga

c(x)(n)
Bálint
fuente
2

C 144 130 bytes

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

Versión sin golf:

//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;
 }

Gracias Kevin por guardar algunos bytes!

Abel Tom
fuente
Puede guardar algunos bytes masajeando las definiciones de funciones:F(m){...}f(x,n)float x;{...}
Kevin
Como u * 1 == u, puede hacer el bucle en la primera función, ya sea while(m)u*=m--o u=m;while(--m)u*=m(misma longitud)
Kevin
i<=n-1es lo mismo quei<n
Kevin
@ Kevin Gracias, tienes toda la razón, no he jugado al golf en mucho tiempo. :)
Abel Tom
2
101 bytes
ceilingcat
2

Stax , 12 bytes

ü┘·.ⁿYeò≥Vîû

Ejecutar y depurarlo

Desempaquetado, sin golf y comentado, se ve así.

            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

Ejecute este

recursivo
fuente
1

JavaScript, 59 bytes

x=>k=n=>--n?k(n)+(-1)**n*x**(n*=2)/f(n):1
f=p=>p?p*f(p-1):1

Pruébalo en línea!

fəˈnɛtɪk
fuente
Esto es 65 bytes
Bálint
@ Bálint había cometido un error al copiar los cambios. (n) se suponía que solo era n
fəˈnɛtɪk
1

PHP, 76 bytes

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

toma Xy Nde los argumentos de la línea de comandos; correr con -r.

bucle $ide 0a N*2-1, asimiento fac($i)en $f; si $ies par, agregue término a la suma $s. imprimir suma


Desearía tener números complejos (con una M_Iunidad imaginaria);
Lo haría simplemente se multiplican $fcon M_I*++$iy ahorro 7 bytes.

Quizás Mathematica pueda hacer eso. Pero Mathematica no tiene que hacerlo.

Yo podría salvar a dos bytes con cos(M_PI*$i/2)en lugar de $i&1?:y (-1)**$k++;
pero sería un poco extraño usar un coseno incorporado para construir una función coseno.

Titus
fuente
1

Axioma, 36 bytes

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

Construya el infinito (en el sentido finito pero se puede pedir construir la lista de 2 * n elementos si la PC tiene suficiente memoria) lista de sumas parciales para la serie de Taylor para cos (x) calcular en 'a', en "eval ( taylor (cos (x)), a) "; obtiene el elemento 2 * n de esa lista en ". (2 * n)". Casos de prueba:

(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
RosLuP
fuente
1

J , 17 bytes

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

Pruébalo en línea!

Utiliza un incorporado , que supongo que está bien.

Desafortunadamente, no sé cómo trabajar bien con funciones que toman argumentos mediante currículum como este, así que tuve que hacerlo explícitamente. Estoy seguro de que hay una manera de hacerlo de manera tácita o más corta.

col
fuente