The Pedant's Cosine

29

4

My boss just told me to write a cosine function. Being a good math geek, my mind immediately conjured the appropriate Taylor Series.

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

However, my boss is very picky. He would like to be able to specify exactly how many terms of the Taylor Series to compute. Can you help me write this function?

Your Task

Given a floating point value x from 0 to 2 pi and a positive integer n less than 100, compute the sum of the first n terms of the Taylor series given above for cos(x).

This is , so shortest code wins. Input and output can be taken in any of the standard ways. Standard loopholes are forbidden.

Notes

  • Input can be taken in any reasonable form, as long as there is a clear separation between x and n.
  • Input and output should be floating-point values, at least as accurate as calculating the formula using single-precision IEEE floating point numbers with some standard rounding rule.
  • If it makes sense for the language being used, computations may be done using exact rational quantities, but the input and output shall still be in decimal form.

Examples

 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

Posted 2017-04-16T18:19:23.023

Reputation: 1 817

1I'm assuming that n is also greater than 0? – GamrCorps – 2017-04-16T18:24:29.633

@GamrCorps n will be greater than zero, yes. – Silvio Mayolo – 2017-04-16T20:02:22.520

@RosLuP I'm not sure I understand your question, but the challenge is to produce the sum of the first n terms of the Taylor series stated in the problem, so the Taylor series about x = 2 or any other point will not suffice. – Silvio Mayolo – 2017-04-16T20:03:07.953

@SilvioMayolo ok i make one error, not rember well, yes sin(x) or cos(x) Taylor series would be ok in all R – RosLuP – 2017-04-16T20:14:18.780

8I'd say they technically isn't what pedant means, but that would be too meta. – PyRulez – 2017-04-17T02:05:34.073

8If your Boss wants you write a good or at least readable function, you're in the wrong place. – Roman Gräf – 2017-04-17T08:25:49.953

2A truly picky boss would want to calculate cosine using something a little more efficient (and accurate) than Taylor series... – PM 2Ring – 2017-04-18T11:49:37.223

6@PM2Ring That would not be picky, that would be being reasonable. Taylor series is really the crudest option. – user1997744 – 2017-04-18T15:51:43.620

If you are rounding, you shouldn't use .... If you are going to use ..., use the exact digits up until that point. – HyperNeutrino – 2017-04-19T13:10:26.447

Answers

64

Operation Flashpoint scripting language, 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}

Call with:

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]

Output:

enter image description here

Input and output should be floating-point values, at least as accurate as calculating the formula using single-precision IEEE floating point numbers with some standard rounding rule.

I'm fairly sure that the numbers are single-precision IEEE floating point numbers, even though in the printed output the longer decimals are not that precise. It is the printing that rounds the numbers like that, actually the numbers are more precise.

For instance, a=1.00001;b=1.000011;hint format["%1\n%2\n%3", a, b, a==b] will output this:

1.00001
1.00001
false

So clearly the actual precision of the numbers is greater than the printed precision.

Steadybox

Posted 2017-04-16T18:19:23.023

Reputation: 15 798

10But why? – orlp – 2017-04-16T23:31:04.717

16@orlp Why not ? – Steadybox – 2017-04-16T23:33:18.010

3

@orlp I think the more appropriate question to ask is: why isn't the Operation Flashpoint scripting language a variant of ArnoldC?

– ceilingcat – 2017-04-17T16:40:16.843

@ceilingcat GET TO THE CHOPPER

– Steadybox – 2017-04-17T18:00:18.843

Accept this! I can't stop ROFL. Pure genius! And the first comments...to the point. And @ceilingcat , thank you for closing THIS gap in my knowledge about programming languages! – GeroldBroser reinstates Monica – 2017-04-18T00:20:40.680

2Hmmm… do you enter the input by shooting a given number of rounds [n] to the given compass direction [x]? Operation Flashpoint! – Mormegil – 2017-04-18T08:35:57.763

14@Mormegil Well, generally no, but that can be done with this piece of 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}}}] - Shooting to some direction increments the counter, and then shooting to another direction calls the cosine function with the earlier direction and the number of shots in that direction. – Steadybox – 2017-04-18T10:10:22.197

1In the spirit of pedantry and the question, your "Call with" section uses a lowercase f but your function submission uses an uppercase F – caird coinheringaahing – 2017-10-28T23:58:59.583

2@cairdcoinheringaahing I see your excellent point of pedantry and raise you another one: The game's scripting language does not care about letter case. All names are case-insensitive, so the f and F disparity does not matter. – Steadybox – 2017-10-29T01:31:37.150

13

05AB1E, 14 11 bytes

FIn(NmN·!/O

Try it online!

Explanation

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

Posted 2017-04-16T18:19:23.023

Reputation: 50 798

@JamesHolderness: Yes, the language has gone through a pretty major overhaul since then. A weird bug seem to have afflicted ², but it can instead be replaced by I. – Emigna – 2018-01-03T19:08:55.127

10

Mathematica, 49 41 39 31 bytes

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

Old, more "fun" version: (39 bytes)

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

Saved 10 bytes thanks to @Pavel and 8 thanks to @Greg Martin!

GamrCorps

Posted 2017-04-16T18:19:23.023

Reputation: 7 058

9While Mathematica's Series capability is indeed awesome and fun, it turns out the by-hand implementation Sum[(-#^2)^k/(2k)!,{k,0,#2-1}]& is shorter here. – Greg Martin – 2017-04-16T19:05:18.430

10

MATL, 14 bytes

U_iqE:2ep/YpsQ

Try it online! Or verify all test cases.

Explanation with example

All numbers have double precision (this is the default).

Consider inputs 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

Posted 2017-04-16T18:19:23.023

Reputation: 87 464

9

Jelly, 12 11 bytes

ḶḤµ⁹*÷!_2/S

Try it online!

How?

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

Posted 2017-04-16T18:19:23.023

Reputation: 67 804

8

Jelly, 22 bytes

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

This is a full program which takes n as the first argument and x as the second.

Explanation:

              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

Posted 2017-04-16T18:19:23.023

Reputation: 7 021

7Welcome to PPCG! – Martin Ender – 2017-04-16T22:16:48.130

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)

If using Python 2, be sure to pass x as a float, not an integer, but I my understanding is that it doesn't matter if you're using Python 3.

Neil

Posted 2017-04-16T18:19:23.023

Reputation: 95 035

5

TI-Basic, 41 40 bytes

Prompt X,N
sum(seq((-(X+1E-49)2)^Q/((2Q)!),Q,0,N-1
1E-49 is added to the angle because TI-Basic throws an error for 0^0, it's just large enough to not cause the error, and it is not large enough to change the answer.

pizzapants184

Posted 2017-04-16T18:19:23.023

Reputation: 3 174

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

Takes curried inputs (x)(n).

Neil

Posted 2017-04-16T18:19:23.023

Reputation: 95 035

Why not make it a snippet? – Arjun – 2017-04-17T04:27:29.477

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

Detailed

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

Detailed

#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

Posted 2017-04-16T18:19:23.023

Reputation: 1 435

96b version c(0.5, 80) => NaN, for overflow f(80)=0 – l4m2 – 2018-01-03T06:33:24.807

@l4m2 recursive functions are here for the purpose of golfing, but they're impractical as they can easily overflow as the number of calls exceed the call-stack limit, & even with higher limits it's a waste of resource, for the solution above try smaller numbers. – Khaled.K – 2018-01-03T12:58:32.790

1Problem directly say n<100 so you at least don't go that far in the range. Not stack overflow – l4m2 – 2018-01-03T13:25:40.920

If problem say n<100 and you use O(2^n) solution I guess it's okay, as long as it eventually retuan the result – l4m2 – 2018-01-03T13:26:28.103

1FYI, the NaN result has got nothing to do with recursion - it's an overflow of the factorial calculation which is using integers when it should be using floats (198! is never going to fit in an int). – James Holderness – 2018-01-03T19:11:44.533

4

R, 70 64 bytes

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

saved 6 bytes thanks to pizzapants184's answer with the (-x^2)^y trick

65 bytes:

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

pretty much the naive implementation of this but a tiny bit golfed; returns an anonymous function that computes the Taylor series to the specified n

  • using a Reduce takes one more byte as init has to be set to 0
  • uses gamma(n+1) instead of factorial(n)
  • 1:n-1 is equivalent to 0:(n-1)

Giuseppe

Posted 2017-04-16T18:19:23.023

Reputation: 21 077

4

C, 71 bytes

using Horner scheme

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

Ungolfed version:

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

Posted 2017-04-16T18:19:23.023

Reputation: 371

On which platform does this work? – anatolyg – 2017-04-18T09:52:50.283

3

oK, 38 bytes

This also works in k, but takes 39 bytes because one ' has to be written as /: instead (at least, in kmac 2016.06.28 it does).

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

Explanation:

Let's start with the middle bit. (*/y#x) is exponentiation, it is equivalent to x^y. */1+!y would be y!, or y factorial. % is division. Therefore the function in the middle is middle(x,y) = (x^y)/(y!).

Now the bit on the right, to which the function above gets applied. 2*!y is {0, 2, 4, ..., 2*(y-1)}. x,' prepends x to every item in that list, turning it into {(x, 0), (x, 2), (x, 4), ..., (x, 2*(y-1))}. The .' then applies middle to every pair of numbers (map, essentially).

Finally, (y#1 -1)* multiplies the result by 1 or -1 (alternating), and +/ takes the sum.

zgrep

Posted 2017-04-16T18:19:23.023

Reputation: 1 291

3

Haskell, 71 Bytes

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

This is a pretty boring answer that's not too hard to decipher. The fromIntegral really bites, though. (The / operator requires operands of the same numeric type in Haskell, and coercing between numeric types is not allowed without a wordy function.)

Enderperson1010

Posted 2017-04-16T18:19:23.023

Reputation: 71

1A list comprehension can save you a few bites: f x n=sum[(-1)^i*x^(2*i)/fromIntegral(product[1..2*i])|i<-[0..n-1]] – Julian Wolf – 2017-04-17T00:08:29.890

1Welcome to PPCG and Haskell golfing in particular! – Laikoni – 2017-04-17T07:19:30.750

3

Jelly, 12 bytes

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

Try it online!

How it works

²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

Posted 2017-04-16T18:19:23.023

Reputation: 196 637

3

Haskell, 61 bytes

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

This seemed different enough from the other Haskell solution to warrant a separate answer. Implementation should be pretty self-explanatory—call with x#n where x is the number the cosine of which is to be computed and n is the order of the partial sum to be taken.

Julian Wolf

Posted 2017-04-16T18:19:23.023

Reputation: 1 139

You can save quite a few bytes by removing the fromIntegral and using ** in place of ^, such as this

– B. Mehta – 2018-05-04T04:33:17.503

x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]] saves 3 more bytes. – Lynn – 2018-05-04T12:14:24.413

3

Pyth, 16 bytes

sm_Fc^vzyd.!yddU

Accepts n first, then x. Example run.

Steven H.

Posted 2017-04-16T18:19:23.023

Reputation: 2 841

3

Pyt, 37 34 33 bytes

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

mudkip201

Posted 2017-04-16T18:19:23.023

Reputation: 833

3

J, 26 24 Bytes

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

-2 bytes thanks to @cole

I originally planned to use a cyclic gerund to alternate between adding and subtracting, but couldn't get it to work.

Explanation:

                    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

Posted 2017-04-16T18:19:23.023

Reputation: 970

124 bytes: +/@:(!@]%~^*_1^2%~])2*i. Gonna investigate a cyclic gerund: it probably failed since J evaluates / right-to-left so you need to use |. (or maybe you accounted for this and still had difficulty). – cole – 2018-01-03T08:30:57.293

3

Perl 6, 53 bytes

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

Try it online!

This actually computes the complex exponential e for twice the number of requested terms and then takes the real part.

Sean

Posted 2017-04-16T18:19:23.023

Reputation: 4 136

2

MATLAB with Symbolic Math Toolbox, 57 bytes

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

This defines an anonymous function with that takes double inputs x,n and outputs the result as a double.

Example (tested on 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

Posted 2017-04-16T18:19:23.023

Reputation: 87 464

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

Ungolfed Version:

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

Thanks Kevin for saving some bytes!

Abel Tom

Posted 2017-04-16T18:19:23.023

Reputation: 1 150

You can save a few bytes by massaging the function definitions: F(m){...}f(x,n)float x;{...} – Kevin – 2017-04-19T03:03:36.357

Since u * 1 == u, you can make the loop in the first function either while(m)u*=m-- or u=m;while(--m)u*=m (same length) – Kevin – 2017-04-19T03:12:56.123

i<=n-1 is the same as i<n – Kevin – 2017-04-19T03:17:48.387

@Kevin Thanks, you're absolutely right, have not golfed in a while now. :) – Abel Tom – 2017-04-20T16:20:39.363

You probably could save some extra bytes if you use f() recursively instead of a loop therein. If you also use the ternary operator your whole function body becomes a one-liner with a few basic math. See my answer.

– GeroldBroser reinstates Monica – 2017-04-21T01:53:14.613

2101 bytes – ceilingcat – 2018-11-27T00:59:20.287

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

To use it:

Press F12, type in the function and then do

c(x)(n)

Bálint

Posted 2017-04-16T18:19:23.023

Reputation: 1 847

2

Tcl, 126 bytes

proc c {x n k\ 0 r\ 0} {proc F n {expr $n?($n)*\[F $n-1]:1}
time {set r [expr $r+-1**$k*$x**(2*$k)/[F 2*$k]]
incr k} $n
set r}

Try it online!

sergiol

Posted 2017-04-16T18:19:23.023

Reputation: 3 055

Failed outgolf: 129 – sergiol – 2018-05-04T00:32:12.687

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

recursive

Posted 2017-04-16T18:19:23.023

Reputation: 8 616

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

Try it online!

fəˈnɛtɪk

Posted 2017-04-16T18:19:23.023

Reputation: 4 166

This is 65 bytes – Bálint – 2017-04-16T20:22:28.580

@Bálint had made a mistake in copying the changes over. (n) was supposed to just be n – fəˈnɛtɪk – 2017-04-16T22:12:50.850

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

RosLuP

Posted 2017-04-16T18:19:23.023

Reputation: 3 036

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.

Titus

Posted 2017-04-16T18:19:23.023

Reputation: 13 814

1

Java, 120 characters

package p;class C{double r;double c(double x,double c,long d,int i){return i>0?r+=c(x,-c/x/x,d/(4*i*i-2*i),--i)+c/d:r;}}

With comments and whitespaces:

C.java

/*
 * Class 'C' (for 'Cosine').
 * Copyright (C) 2017 Gerold 'Geri' Broser (geribro@users.sourceforge.net)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package p;

/** Class 'C' (for Cosine).
 *  
 * @author Gerold 'Geri' Broser
 * @version 17.04.21
 * @see https://codegolf.stackexchange.com/questions/116705/the-pedants-cosine
 */
class C {

    /** The added up results of the polynomial's terms.
     */
    double r;

    /** This one-liner method 'c' (for calculate) returns the part (i=n-1) of a 
     *  cosine of a given angle 'x' that's calculated from the second term of a
     *  Taylor series of n polynomial terms onwards (or backwards until the 
     *  second term [i=1], to be precise, see below).
     *  
     *  It achieves this by doing the following:
     * 
     * ● It doesn't calculate the first term since it is always 1 anyway.
     * 
     * ● It uses recursion for calculating the terms of the polynomial.
     * 
     * ● It calculates from the rightmost term back to the leftmost. Such avoiding
     *   to keep the upper boundary stored till the end for the recursion's stop 
     *   condition.
     * 
     * ● It is supplied with values for the counter and denominator of the 
     *   rightmost term at invocation. Such also the user can decide which
     *   library to take for power and factorial. 
     * 
     * ● It calculates the counters and denominators for each term from scratch 
     *   at each recursion but uses the values calculated at the previous 
     *   recursion. Such the new values can be calculated by using trivial 
     *   parenthesis, division, multiplication, decrement and negation only.
     *   This doesn't only save characters but probably is also faster than 
     *   power and factorial.
     *   [It could be made be even faster for x=2^n, n ∈ N, because we can 
     *   use the unsigned right shift operator '>>>' instead of divisions then
     *   (see method 'calculateForXisPowerOfTwo()' of class 'Cosine').]
     * 
     * @param x angle (independent variable) in radians
     * @param c counter of last term specified by index 'i' including proper sign
     *          (see class 'CTest')
     * @param d denominator of last term specified by index 'i' (see class 'CTest')
     * @param i index of last term used in the calculation (=number of terms 'n'
     *          minus 1; Σ's upper boundary)
     * 
     * @see https://en.wikipedia.org/wiki/Taylor_series#Trigonometric_functions
     */

    // Copy the following three lines to immediately after the function header for testing: 
    //  System.out.printf(
    //          "c(): x:%4.1f  c:%24.17f  d:%,19d  i:%2d  t:%40.35f%n",
    //          x, c, d, i, c / d);

    // Position of 'i' is relevant here, since it is prefix-decremented inline!
    double c( double x, double c, long d, int i ) {
        return i > 0
                ? r += c(
                    x,
                    -c / x / x,
                    d / (4 * i * i - 2 * i),
                    --i )
                    + c / d
                : r;
    } // c()
} // C

CTest.java

/*
 * Class 'CTest' (for 'Cosine Test').
 * Copyright (C) 2017 Gerold 'Geri' Broser (geribro@users.sourceforge.net)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package p;

import org.apache.commons.math3.util.CombinatoricsUtils;

/** Test class for methods 'c' (for calculate) of class 'C' (for Cosine).
 * 
 * @author Gerold 'Geri' Broser
 * @version 17.04.21
 * @see https://codegolf.stackexchange.com/questions/116705/the-pedants-cosine
 */
public class CTest {

    /** The Unicode character 'ₛ' is the subscript character for 's'. It stands for the plural 's' 
     *  in the array's names. ('xs' wasn't matching my BMI. 'ns' looked like a system that we have
     *  overcome since decades and like the German abbreviation for...I'm leaving that one out now.)
     * 
     * @param args command line arguments
     */
    public static void main( String[] args ) {

        double[] xₛ = { .0, .5, .5, .5, .5, 2., 2. };
        int[] nₛ = { 1, 1, 2, 4, 9, 2, 5 };

        System.out.println(
                "┌────┬─────┬───┬───────────────────────┐\n" +
                "│ No │  x  │ n │        cos(x)         │\n" +
                "├────┤─────┼───┼───────────────────────┤" );
        for ( int i = 0; i < xₛ.length; i++ ) {

            System.out.printf( "│ %d. │ %2.1f │ %d │ %,21.18f │%n",
                    i + 1,
                    xₛ[i], // x (angle)
                    nₛ[i]--, // n (number of terms of the polynomial, decreased for further processing as index)
                    1.0 + new C().c(
                            xₛ[i], // x (angle in radians)
                            Math.pow( -1, nₛ[i] ) // negate alternating starting with minus for the second term 
                                    * Math.pow( xₛ[i], 2 * nₛ[i] ), // counter for the rightmost term (c)
                            CombinatoricsUtils.factorial( 2 * nₛ[i] ), // denominator for the rightmost term (d)
                            nₛ[i] // index of last term of the polynomial 
                    ) );

        } // for ( C test case )
        System.out.println( "└────┴─────┴───┴───────────────────────┘" );
    } // main()
} // CTest

Output

┌────┬─────┬───┬───────────────────────┐
│ No │  x  │ n │        cos(x)         │
├────┤─────┼───┼───────────────────────┤
│ 1. │ 0,0 │ 1 │  1,000000000000000000 │
│ 2. │ 0,5 │ 1 │  1,000000000000000000 │
│ 3. │ 0,5 │ 2 │  0,875000000000000000 │
│ 4. │ 0,5 │ 4 │  0,877582465277777700 │
│ 5. │ 0,5 │ 9 │  0,877582561890372800 │
│ 6. │ 2,0 │ 2 │ -1,000000000000000000 │
│ 7. │ 2,0 │ 5 │ -0,415873015873015950 │
└────┴─────┴───┴───────────────────────┘

GeroldBroser reinstates Monica

Posted 2017-04-16T18:19:23.023

Reputation: 113

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.

cole

Posted 2017-04-16T18:19:23.023

Reputation: 3 526

1

Clean, 77 bytes

import StdEnv
?x n=sum[(-1.0)^(p/2.0)*x^p/prod[1.0..p]\\p<-take n[0.0,2.0..]]

Try it online!

Οurous

Posted 2017-04-16T18:19:23.023

Reputation: 7 916

1

Pari/GP, 35 bytes

f(x,n)=sum(i=0,n-1,(-x^2)^i/(2*i)!)

Try it online!

alephalpha

Posted 2017-04-16T18:19:23.023

Reputation: 23 988

1

F#, 177 146 bytes

let rec f x=if x<2 then 1 else f(x-1)*x
let i n x=(pown -1.0 n)*(pown x (2*n))/float(f(2*n))
let t x k=seq{for j=0 to(k-1)do yield i j x}|>Seq.sum

Try it online!

Shaved off 31 bytes thanks to Emmanuel showing me operators in F# that I wasn't aware of. I had a look at Microsoft.FSharp.Core.Operators and found some useful stuff there. Thanks a million!

f is a recursive factorial function. i is one item in the series, and t is the actual Taylor Series itself - iterate through from 0 to k-1, evaluating i at each stage, and sum the results.

Ciaran_McCarthy

Posted 2017-04-16T18:19:23.023

Reputation: 689

1You could try with the **exponential operator. – Emmanuel – 2018-05-04T15:46:09.167

Ah, I wasn't aware that F# had an exponential operator! This is what I love about Code Golf - I'm inexperienced with F# so I didn't know about ** or any of the other goodies in Microsoft.FSharp.Core.Operators. Now I know about ** and pown and a load of other good things, and I can take 31 bytes off the solution. Thanks a lot, I really appreciate it! – Ciaran_McCarthy – 2018-05-04T22:03:35.207