Косинус педанта


29

Мой босс только что сказал мне написать функцию косинуса. Будучи хорошим математическим фанатом, мой разум сразу же вызвал соответствующую серию Тейлора.

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

Тем не менее, мой босс очень разборчив. Он хотел бы иметь возможность точно указать, сколько терминов из ряда Тейлора вычислить. Можете ли вы помочь мне написать эту функцию?

Твое задание

Учитывая значение xс плавающей запятой от 0до 2 piи положительное целое число nменьше чем 100, вычислите сумму первых nчленов ряда Тейлора, приведенных выше для cos(x).

Это , поэтому выигрывает самый короткий код. Ввод и вывод могут быть приняты любым из стандартных способов. Стандартные лазейки запрещены.

Заметки

  • Входные данные могут быть приняты в любой разумной форме, если есть четкое разделение между xи n.
  • Вход и выход должны быть значениями с плавающей запятой, по крайней мере, такими же точными, как вычисление формулы с использованием чисел с плавающей запятой одинарной точности IEEE с некоторым стандартным правилом округления.
  • Если это имеет смысл для используемого языка, вычисления могут выполняться с использованием точных рациональных величин, но входные и выходные данные все еще должны быть в десятичной форме.

Примеры

 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
Я предполагаю, что nэто также больше, чем 0?
GamrCorps

8
Я бы сказал, что технически они не имеют в виду педанта, но это было бы слишком мета.
PyRulez

8
Если ваш босс хочет, чтобы вы написали хорошую или хотя бы читабельную функцию, вы попали не туда.
Роман Греф

2
Действительно придирчивый босс хотел бы, чтобы вычислить косинус , используя что - то немного более эффективное (и точное) , чем ряд Тейлора ...
PM 2Ring

6
@ PM2Ring Это не было бы разборчиво, это было бы разумно. Серия Тейлор действительно самый крутой вариант.
user1997744

Ответы:


64

Язык сценариев работы Flashpoint , 165 157 байт

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}

Звоните с:

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]

Выход:

введите описание изображения здесь

Вход и выход должны быть значениями с плавающей запятой, по крайней мере, такими же точными, как вычисление формулы с использованием чисел с плавающей запятой одинарной точности IEEE с некоторым стандартным правилом округления.

Я вполне уверен, что числа являются числами с плавающей точкой IEEE одинарной точности, хотя в печатном выводе более длинные десятичные числа не столь точны. Именно печать округляет такие числа, на самом деле цифры более точные.

Например, a=1.00001;b=1.000011;hint format["%1\n%2\n%3", a, b, a==b]выведет это:

1.00001
1.00001
false

Очевидно, что фактическая точность чисел выше точности печати.



16
@orlp Почему бы и нет?
Steadybox

3
@orlp Я думаю, что более подходящий вопрос: почему язык сценариев Operation Flashpoint не является вариантом ArnoldC ?
terracecat

2
Хммм ... вводите ли вы ввод, стреляя заданным количеством раундов [n] в заданное направление компаса [x]? Flash Операция Flashpoint!
Mormegil

14
@ Mormegil Ну, как правило, нет, но это можно сделать с помощью этого фрагмента кода: 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}}}]- Съемка в каком-то направлении увеличивает счетчик, а затем съемка в другом направлении вызывает функцию косинуса с более ранним направлением и количеством снимков в этом направлении.
Steadybox

13

05AB1E , 14 11 байт

FIn(NmN·!/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: Да, с тех пор язык претерпел довольно серьезные изменения. Странная ошибка, похоже, огорчила ², но вместо этого ее можно заменить на I.
Emigna

10

MATL , 14 байтов

U_iqE:2ep/YpsQ

Попробуйте онлайн! Или проверьте все тестовые случаи .

Пояснение с примером

Все числа имеют двойную точность (это значение по умолчанию).

Рассмотрим входы 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 байт

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

Старая, более «веселая» версия: (39 байт)

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

Благодаря @Pavel сэкономлено 10 байтов, а благодаря @Greg Martin - 8!


9
Хотя Seriesвозможности Mathematica действительно потрясающие и увлекательные, оказывается, что ручная реализация Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]&здесь короче.
Грег Мартин

9

Желе , 12 11 байт

ḶḤµ⁹*÷!_2/S

Попробуйте онлайн!

Как?

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

Желе, 22 байта

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

Это полная программа, которая принимает n в качестве первого аргумента и x в качестве второго.

Объяснение:

              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
Добро пожаловать в PPCG!
Мартин Эндер

6

Python, 54 байта

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

Если вы используете Python 2, обязательно передайте x как число с плавающей точкой, а не как целое число, но, насколько я понимаю, не имеет значения, используете ли вы Python 3.


5

TI-Basic, 41 40 байт

Prompt X,N
sum(seq((-(X+1E-49)2)^Q/((2Q)!),Q,0,N-1
1E-49 добавляется к углу, потому что TI-Basic выдает ошибку для 0 ^ 0, она просто достаточно велика, чтобы не вызвать ошибку, и недостаточно велика, чтобы изменить ответ.


4

C 96 байтов

Рекурсивный 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;}

Детальнее

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
}

Прогрессивно-рекурсивный, 133 байта 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;}

Детальнее

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

Версия c(0.5, 80)f(80)=0
96b

@ l4m2 рекурсивные функции здесь для целей игры в гольф, но они непрактичны, так как могут легко переполняться, когда количество вызовов превышает предел стека вызовов, и даже с более высокими ограничениями это пустая трата ресурсов для решения выше меньшие числа.
Khaled.K

1
Задача прямо скажем, n<100чтобы вы, по крайней мере, не заходили так далеко в диапазоне. Не переполнение стека
l4m2

Если проблема говорит, n<100и вы используете O(2^n)решение, я думаю, что все в порядке, если это в конечном итоге приведет к результату
l4m2

1
К вашему сведению, результат NaN не имеет ничего общего с рекурсией - это переполнение факториального вычисления, которое использует целые числа, когда оно должно использовать числа с плавающей запятой (198! Никогда не поместится в int).
Джеймс Холдернесс

4

JavaScript (ES6), 46 байт

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

Принимает карри вводов (х) (п).


Почему бы не сделать его фрагментом?
Арджун

4

C 71 байт

по схеме Хорнера

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

Безголовая версия:

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

На какой платформе это работает?
Анатолий

4

R, 70 64 байта

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

спасло 6 байт благодаря ответу pizzapants184 с помощью (-x ^ 2) ^ уловки

65 байт:

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

довольно наивная реализация этого, но чуть-чуть в гольфе; возвращает анонимную функцию, которая вычисляет ряд Тейлора для указанного n

  • использование Reduce занимает еще один байт, так как initдолжно быть установлено в 0
  • использует gamma(n+1)вместоfactorial(n)
  • 1:n-1 эквивалентно 0:(n-1)

3

ок , 38 байт

Это также работает в k , но занимает 39 байтов, потому что каждый 'должен быть записан как /:вместо (по крайней мере, в kmac 2016.06.28 это делает).

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

Объяснение:

Давайте начнем со среднего бита. (*/y#x)это возведение в степень, это эквивалентно x^y. */1+!yбудет y!или yфакториал. %это разделение. Поэтому функция посередине есть middle(x,y) = (x^y)/(y!).

Теперь бит справа, к которому применяется вышеуказанная функция. 2*!yесть {0, 2, 4, ..., 2*(y-1)}. x,'присваивает xкаждому элементу в этом списке, превращая его в {(x, 0), (x, 2), (x, 4), ..., (x, 2*(y-1))}. .'Затем применяет middleк каждой паре чисел ( mapпо существу).

Наконец, (y#1 -1)*умножает результат на 1 или -1 (поочередно) и +/получает сумму.


3

Haskell, 71 байт

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

Это довольно скучный ответ, который не слишком сложно расшифровать. fromIntegralДействительно кусается, хотя. ( /Оператору требуются операнды с одинаковым числовым типом в Haskell, и принудительное использование числовых типов невозможно без многословной функции.)


1
f x n=sum[(-1)^i*x^(2*i)/fromIntegral(product[1..2*i])|i<-[0..n-1]]
Джулиан Вольф

1
Добро пожаловать в PPCG и Haskell в гольф в частности!
Лайкони

3

Желе , 12 байт

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

Попробуйте онлайн!

Как это работает

²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 байт

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

Это казалось достаточно отличным от другого решения Haskell, чтобы гарантировать отдельный ответ. Реализация должна быть достаточно понятной - вызывать x#nгде xчисло, косинус которого должен быть вычислен, и nпорядок частичной суммы, которую нужно взять.


Вы можете сэкономить немало байтов, удалив fromIntegralи использовав **вместо них ^, например, это
Б. Мехта

x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]]экономит еще 3 байта.
Линн


3

J, 26 24 байта

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

-2 байта благодаря @cole

Изначально я планировал использовать циклический герунд для чередования сложения и вычитания, но не смог заставить его работать.

Объяснение:

                    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 байта: +/@:(!@]%~^*_1^2%~])2*i.собираюсь исследовать циклический герунд: он, вероятно, потерпел неудачу, поскольку J оценивает /справа налево, поэтому вам нужно использовать |.(или, возможно, вы учли это и все еще испытывали трудности).
Коул

3

Perl 6 , 53 байта

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

Попробуйте онлайн!

Это фактически вычисляет комплексную экспоненту e для двойного числа запрошенных членов и затем принимает действительную часть.


2

MATLAB с символьным набором математических инструментов, 57 байт

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

Это определяет анонимную функцию , которая принимает с doubleвходами x, nи выводит результат в виде double.

Пример (проверено на 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 байт

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

Чтобы использовать это:

Нажмите F12, введите функцию и затем выполните

c(x)(n)

2

C 144 130 байтов

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

Безголовая версия:

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

Спасибо Кевину за сохранение некоторых байтов!


Вы можете сохранить несколько байтов, массируя определения функций:F(m){...}f(x,n)float x;{...}
Кевин,

Поскольку u * 1 == u, вы можете сделать цикл в первой функции либо ( while(m)u*=m--или u=m;while(--m)u*=mодинаковой длины)
Кевин,

i<=n-1так же, какi<n
Кевин

@Kevin Спасибо, ты абсолютно прав, давно не играл в гольф. :)
Абель Том



2

Stax , 12 байт

ü┘·.ⁿYeò≥Vîû

Запустите и отладьте его

Распакованный, размазанный и прокомментированный, это выглядит так.

            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

Запустите этот



1

PHP, 76 байт

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

берет Xи Nиз аргументов командной строки; беги с -r.

цикл $iот 0до N*2-1, удерживать fac($i)в $f; если $iчетное, добавьте термин к сумме $s. печать суммы.


Я хотел бы иметь комплексные числа (с M_Iмнимой единицей);
Я бы просто умножить $fс M_I*++$iи сохранить 7 байт.

Может быть, Mathematica может сделать это. Но Mathematica не обязана.

Я мог бы сохранить два байта с cos(M_PI*$i/2)вместо $i&1?:и (-1)**$k++;
но было бы немного странно использовать встроенный косинус для построения функции косинуса.


1

Аксиома, 36 байт

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

Построить бесконечный (в смысле конечный, но можно попросить построить список из 2 * n элементов, если на компьютере достаточно памяти) список частичных сумм для ряда Тейлора для cos (x), вычисляемый в «a», in «eval ( Тейлор (COS (х)), а) "; получает элемент 2 * n этого списка в ". (2 * n)". Тестовые случаи:

(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 байт

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

Попробуйте онлайн!

Использует встроенный , который, я полагаю, в порядке.

К сожалению, я действительно не знаю, как хорошо работать с функциями, которые принимают аргументы через карри, как это, поэтому я должен был сделать это явно. Я уверен, что есть способ сделать это молчаливо или короче.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.