O cosseno do pedante


29

Meu chefe acabou de me dizer para escrever uma função cosseno. Sendo um bom nerd de matemática, minha mente imediatamente conjurou a Série Taylor apropriada.

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

No entanto, meu chefe é muito exigente. Ele gostaria de poder especificar exatamente quantos termos da série Taylor computar. Você pode me ajudar a escrever esta função?

Sua tarefa

Dado um valor de ponto flutuante xde 0para 2 pie um número inteiro positivo nmenor que 100, calcule a soma dos primeiros ntermos da série Taylor dados acima para cos(x).

Isso é , então o código mais curto vence. A entrada e a saída podem ser obtidas de qualquer uma das maneiras padrão. As brechas padrão são proibidas.

Notas

  • A entrada pode ser obtida de qualquer forma razoável, desde que haja uma separação clara entre xe n.
  • A entrada e a saída devem ser valores de ponto flutuante, pelo menos tão precisos quanto o cálculo da fórmula usando números de ponto flutuante IEEE de precisão única com alguma regra de arredondamento padrão.
  • Se fizer sentido para o idioma que está sendo usado, os cálculos podem ser feitos usando quantidades racionais exatas, mas a entrada e a saída ainda devem estar na forma decimal.

Exemplos

 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
Estou assumindo que ntambém é maior que 0?
GamrCorps

8
Eu diria que tecnicamente não é o que pedante significa, mas isso seria muito meta.
PyRulez

8
Se o seu chefe deseja que você escreva uma função boa ou pelo menos legível, você está no lugar errado.
Roman Gräf

2
Um verdadeiramente patrão exigente gostaria de cosseno calcular usando algo um pouco mais eficiente (e precisa) de série de Taylor ...
PM 2Ring

6
@ PM2Ring Isso não seria exigente, seria razoável. A série Taylor é realmente a opção mais cruel.
usar o seguinte comando

Respostas:


64

Linguagem de script da operação Flashpoint , 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}

Ligue para:

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]

Saída:

insira a descrição da imagem aqui

A entrada e a saída devem ser valores de ponto flutuante, pelo menos tão precisos quanto o cálculo da fórmula usando números de ponto flutuante IEEE de precisão única com alguma regra de arredondamento padrão.

Tenho certeza de que os números são números de ponto flutuante IEEE de precisão única, embora na saída impressa os decimais mais longos não sejam tão precisos. É a impressão que arredonda os números assim, na verdade os números são mais precisos.

Por exemplo, a=1.00001;b=1.000011;hint format["%1\n%2\n%3", a, b, a==b]produzirá isso:

1.00001
1.00001
false

Tão claramente que a precisão real dos números é maior que a precisão impressa.



16
@orlp Por que não?
Steadybox

3
@orlp Acho que a pergunta mais apropriada é: por que a linguagem de script Operation Flashpoint não é uma variante do ArnoldC ?
ceilingcat

2
Hmmm ... você digita a entrada disparando um determinado número de voltas [n] na direção da bússola [x]? 😍 Operação Flashpoint!
Mormegil 18/04

14
@Megegil Bem, geralmente não, mas isso pode ser feito com 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 em alguma direção incrementa o contador e, em seguida, disparar para outra direção chama a função cosseno com a direção anterior e o número de disparos nessa direção.
precisa saber é o seguinte

13

05AB1E , 14 11 bytes

FIn(NmN·!/O

Experimente online!

Explicação

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: Sim, o idioma passou por uma grande reforma desde então. Um bug estranho parece ter sido afetado ², mas pode ser substituído por I.
Emigna

10

MATL , 14 bytes

U_iqE:2ep/YpsQ

Experimente online! Ou verifique todos os casos de teste .

Explicação com exemplo

Todos os números têm precisão dupla (esse é o padrão).

Considere entradas 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 bytes

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

Versão antiga e mais "divertida": (39 bytes)

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

Economizou 10 bytes graças a @Pavel e 8 graças a @Greg Martin!


9
Embora a Seriescapacidade do Mathematica seja realmente incrível e divertida, a implementação manual Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]&é mais curta aqui.
Greg Martin

9

Geléia , 12 11 bytes

ḶḤµ⁹*÷!_2/S

Experimente online!

Quão?

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

Gelatina, 22 bytes

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

Este é um programa completo que toma n como o primeiro argumento ex como o segundo.

Explicação:

              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
Bem-vindo ao 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)

Se você estiver usando o Python 2, passe x como um float, não como um número inteiro, mas entendo que não importa se você está usando o Python 3.


5

TI-Basic, 41 40 bytes

Prompt X,N
sum(seq((-(X+1E-49)2)^Q/((2Q)!),Q,0,N-1
1E-49 é adicionado ao ângulo porque o TI-Basic lança um erro para 0 ^ 0, é grande o suficiente para não causar o erro e não é grande o suficiente para alterar a resposta.


4

C, 96 bytes

Recursivo ao vivo

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

Detalhado

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
}

Progressivo Recursivo, 133 bytes Ao 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;}

Detalhado

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

Versão 96b c(0.5, 80)=> NaN, para estourof(80)=0
l4m2

As funções recursivas do @ l4m2 estão aqui com o objetivo de jogar golfe, mas são impraticáveis, pois podem exceder facilmente, pois o número de chamadas excede o limite da pilha de chamadas e, mesmo com limites mais altos, é um desperdício de recursos, para a solução acima, tente números menores.
precisa saber é o seguinte

1
O problema diz diretamente n<100para que você pelo menos não vá tão longe no intervalo. Não estouro de pilha
l4m2

Se o problema exemplo n<100e você usar O(2^n)solução que eu acho que está tudo bem, contanto que, eventualmente, Retuan o resultado
l4m2

1
Para sua informação, o resultado NaN não tem nada a ver com recursão - é um estouro do cálculo fatorial que usa números inteiros quando deveria estar usando floats (198! Nunca vai caber em um 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 com caril (x) (n).


Por que não torná-lo um trecho?
Arjun

4

C, 71 bytes

usando o esquema Horner

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

Versão não destruída:

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

Em qual plataforma isso funciona?
anatolyg

4

R, 70 64 bytes

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

economizou 6 bytes graças à resposta de pizzapants184 com o truque (-x ^ 2) ^ y

65 bytes:

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

praticamente a implementação ingênua disso, mas um pouco minuciosa; retorna uma função anônima que calcula a série Taylor para o n especificado

  • usar um Reduce leva mais um byte, pois initdeve ser definido como 0
  • usa em gamma(n+1)vez defactorial(n)
  • 1:n-1 é equivalente a 0:(n-1)

3

OK , 38 bytes

Isso também funciona em k , mas ocupa 39 bytes porque 'é necessário escrever como um /:(pelo menos no kmac 2016.06.28).

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

Explicação:

Vamos começar com a parte do meio. (*/y#x)é exponenciação, é equivalente a x^y. */1+!yseria y!, ou yfatorial. %é divisão. Portanto, a função no meio é middle(x,y) = (x^y)/(y!).

Agora, o bit à direita, ao qual a função acima é aplicada. 2*!yé {0, 2, 4, ..., 2*(y-1)}. x,'precede xtodos os itens dessa lista, transformando-os em {(x, 0), (x, 2), (x, 4), ..., (x, 2*(y-1))}. O .'então se aplica middlea todos os pares de números ( map, essencialmente).

Por fim, (y#1 -1)*multiplica o resultado por 1 ou -1 (alternando) e +/recebe a soma.


3

Haskell, 71 Bytes

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

Esta é uma resposta bastante chata que não é muito difícil de decifrar. As fromIntegralmordidas realmente, no entanto. (O /operador requer operandos do mesmo tipo numérico em Haskell, e a coação entre tipos numéricos não é permitida sem uma função detalhada.)


1
Uma compreensão da lista pode poupar algumas mordidas:f x n=sum[(-1)^i*x^(2*i)/fromIntegral(product[1..2*i])|i<-[0..n-1]]
Julian Wolf

1
Bem-vindo ao PPCG e Haskell, em particular!
Laikoni

3

Gelatina , 12 bytes

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

Experimente online!

Como 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.


3

Haskell , 61 bytes

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

Isso parecia diferente o suficiente da outra solução Haskell para justificar uma resposta separada. A implementação deve ser bastante autoexplicativa - chame com x#nonde xé o número cujo cosseno deve ser calculado e na ordem da soma parcial a ser tomada.


Você pode salvar alguns bytes removendo fromIntegrale usando **no lugar de ^, como este
B. Mehta

x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]]economiza mais 3 bytes.
Lynn

3

Pyt , 37 34 33 bytes

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

3

J, 26 24 bytes

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

-2 bytes graças a @cole

Inicialmente, planejei usar um gerúndio cíclico para alternar entre adicionar e subtrair, mas não consegui fazê-lo funcionar.

Explicação:

                    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 bytes: +/@:(!@]%~^*_1^2%~])2*i.Vai investigar um gerúndio cíclico: provavelmente falhou, pois J avalia da /direita para a esquerda, então você precisa usá-lo |.(ou talvez você tenha explicado isso e ainda tenha dificuldades).
Cole

3

Perl 6 , 53 bytes

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

Experimente online!

Na verdade, isso calcula o complexo exponencial e para o dobro do número de termos solicitados e, em seguida, assume a parte real.


2

MATLAB com caixa de ferramentas matemática simbólica, 57 bytes

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

Isto define uma função anônima com que leva doubleentradas x, ne emite o resultado como um double.

Exemplo (testado no 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 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 usá-lo:

Pressione F12, digite a função e faça

c(x)(n)

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

Versão Ungolfed:

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

Obrigado Kevin por salvar alguns bytes!


Você pode economizar alguns bytes por massageando as definições de funções:F(m){...}f(x,n)float x;{...}
Kevin

Desde u * 1 == u, você pode fazer o loop na primeira função, quer while(m)u*=m--ou u=m;while(--m)u*=m(mesmo comprimento)
Kevin

i<=n-1é o mesmo que:i<n
Kevin

@ Kevin Obrigado, você está absolutamente certo, não joga golfe há um tempo agora. :)
Abel Tom



2

Stax , 12 bytes

ü┘·.ⁿYeò≥Vîû

Execute e depure

Descompactado, não jogado e comentado, parece com isso.

            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

Execute este



1

PHP, 76 bytes

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

pega Xe Nde argumentos de linha de comando; corra com -r.

laço $ide 0a N*2-1, espera fac($i)em $f; se $ifor par, adicione termo à soma $s. soma de impressão.


Eu gostaria de ter números complexos (com uma M_Iunidade imaginária);
Eu simplesmente multiplicar $fcom M_I*++$ie salvar 7 bytes.

Talvez o Mathematica possa fazer isso. Mas o Mathematica não precisa.

Eu poderia salvar dois bytes com em cos(M_PI*$i/2)vez de $i&1?:e (-1)**$k++;
mas seria um pouco estranho usar um cosseno embutido para criar uma função de cosseno.


1

Axioma, 36 bytes

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

Crie a lista infinita (no sentido finito, mas pode-se pedir para criar a lista de 2 * n elementos se o PC tiver memória suficiente) de somas parciais para a série de Taylor para cos (x) calcular em 'a', em "eval ( taylor (cos (x)), a) "; obtém o elemento 2 * n dessa lista em ". (2 * n)". Casos de teste:

(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 bytes

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

Experimente online!

Usa um built-in , que eu assumo está OK.

Infelizmente, eu realmente não sei como trabalhar bem com funções que aceitam argumentos por meio de currying, então eu tive que fazer isso explicitamente. Tenho certeza de que existe uma maneira de fazê-lo tacitamente ou mais curto.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.