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


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]

Вихід:

enter image description here

Введення та вихід мають бути значеннями з плаваючою комою, принаймні настільки ж точними, як обчислення формули, використовуючи одноточні номери плаваючої точки 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 ?
стельовий кот

2
Гммм ... ви вводите вхід, стріляючи задану кількість раундів [n] до заданого напрямку компаса [x]? 😍 Операція Flashpoint!
Мормегіл

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.
Емінья

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

Математика, 49 41 39 31 байт

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

Стара, більш "весела" версія: (39 байт)

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

Збережено 10 байт завдяки @Pavel та 8 завдяки @Greg Martin!


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

Пітон, 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 передається як float, а не ціле число, але я розумію, що це не має значення, якщо ви використовуєте 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
}

96b версія c(0.5, 80)=> NaN, для переливуf(80)=0
l4m2

Рекурсивні функції @ l4m2 є для цілей гольфу, але вони непрактичні, оскільки вони можуть легко переповнюватись, оскільки кількість викликів перевищує ліміт стека викликів, і навіть при більш високих лімітах це марно витрачайте ресурси, для рішення вище менші числа.
Халед.К

1
Проблема прямо сказати, n<100так що ви, принаймні, не так далеко в діапазоні. Не переповнення стека
l4m2

Якщо проблема скаже, n<100і ви використовуєте O(2^n)рішення, я гадаю, що це нормально, доки це врешті ретуюватиме результат
l4m2

1
FYI, результат NaN не має нічого спільного з рекурсією - це перелив факторіального обчислення, який використовує цілі числа, коли він повинен використовувати floats (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

Займає вивірені входи (x) (n).


Чому б не зробити його фрагментом?
Арджун

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

На якій платформі це працює?
anatolyg

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) ^ y хитрості

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

Хаскелл, 71 байт

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

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


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 з Symbolic Math Toolbox, 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 bytes

ü┘·.ⁿYeò≥Vîû

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

            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

Run this one



1

PHP, 76 bytes

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

takes X and N from command line arguments; run with -r.

loop $i from 0 to N*2-1, hold fac($i) in $f; if $i is even, add term to sum$s. print sum.


I wish I had complex numbers (with M_I as imaginary unit);
I would simply multiply $f with M_I*++$i and save 7 bytes.

Maybe Mathematica can do that. But Mathematica doesn´t have to.

I could save two bytes with cos(M_PI*$i/2) instead of $i&1?: and (-1)**$k++;
but it would feel a bit odd to use a cosine builtin to build a cosine function.


1

Axiom, 36 bytes

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

Build the infinite (in the meaning finite but one can ask to build the list of 2*n elements if PC has enough memory) list of partial sums for the Taylor series for cos(x) calculate in 'a', in "eval(taylor(cos(x)),a)"; gets the 2*n element of that list in ".(2*n)". Test cases:

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

Try it online!

Uses a built-in, which I assume is OK.

Unfortunately, I don't really know how to work well with functions that take arguments via currying like this, so I had to do this explicitly. I'm sure that there is a way to do it tacitly or shorter.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.