29
\$\begingroup\$

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...
\$\endgroup\$
  • 1
    \$\begingroup\$ I'm assuming that n is also greater than 0? \$\endgroup\$ – GamrCorps Apr 16 '17 at 18:24
  • 8
    \$\begingroup\$ I'd say they technically isn't what pedant means, but that would be too meta. \$\endgroup\$ – PyRulez Apr 17 '17 at 2:05
  • 8
    \$\begingroup\$ If your Boss wants you write a good or at least readable function, you're in the wrong place. \$\endgroup\$ – Roman Gräf Apr 17 '17 at 8:25
  • 2
    \$\begingroup\$ A truly picky boss would want to calculate cosine using something a little more efficient (and accurate) than Taylor series... \$\endgroup\$ – PM 2Ring Apr 18 '17 at 11:49
  • 6
    \$\begingroup\$ @PM2Ring That would not be picky, that would be being reasonable. Taylor series is really the crudest option. \$\endgroup\$ – user1997744 Apr 18 '17 at 15:51

33 Answers 33

1
2
1
\$\begingroup\$

Pari/GP, 35 bytes

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

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ You could try with the **exponential operator. \$\endgroup\$ – Emmanuel May 4 '18 at 15:46
  • \$\begingroup\$ 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! \$\endgroup\$ – Ciaran_McCarthy May 4 '18 at 22:03
1
\$\begingroup\$

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 │
└────┴─────┴───┴───────────────────────┘
| improve this answer | |
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.