行人余弦


29

我的老板只是告诉我写一个余弦函数。作为一名数学高手,我立即想到了合适的泰勒级数。

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

但是,我的老板很挑剔。他希望能够精确指定要计算的泰勒级数的项。你能帮我写这个功能吗?

你的任务

给定x0到的浮点值2 pin小于的正整数100,计算n上给出的泰勒级数的第一项的和cos(x)

这是,因此最短的代码获胜。输入和输出可以采用任何标准方式进行。禁止出现标准漏洞。

笔记

  • 输入可以采取任何形式合理的,只要有明确分开xn
  • 输入和输出应为浮点值,至少与使用具有某些标准舍入规则的单精度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
如果老板希望您编写良好的功能或至少具有可读性的功能,那么您来错了地方。
罗曼·格拉夫(RomanGräf)

2
一个真正挑剔的老板想使用比泰勒级数更有效(准确)的东西来计算余弦...
PM 2Ring

6
@ PM2Ring不会挑剔,这是合理的。泰勒级数确实是最粗略的选择。
user1997744 '17

Answers:


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我认为要问的更合适的问题是:为什么操作Flashpoint脚本语言不是ArnoldC的变体?
ceilingcat '17

2
嗯……您是通过向给定的罗盘方向[x]射击给定的回合数[n]来输入输入吗?😍操作闪点!
Mormegil '17

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

05AB1E14 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:是的,自那时以来,该语言经历了相当大的大修。一个怪异的bug似乎困扰了²,但是可以用代替I
Emigna

10

MATL,14个字节

U_iqE:2ep/YpsQ

在线尝试!验证所有测试用例

举例说明

所有数字都具有双精度(这是默认值)。

考虑输入x = 2.0n = 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
虽然Mathematica的Series功能确实很棒,而且很有趣,但事实证明,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!
Martin Ender

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字节

递归 实时

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个字节

#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,18年

@ l4m2递归函数是为了打高尔夫球而设计的,但是它们不切实际,因为当调用数量超过调用堆栈限制时,它们很容易溢出,即使使用更高的限制,也浪费资源,对于上面的解决方案请尝试较小的数字。
Khaled.K,

1
问题是直接说出来的,n<100因此您至少不会走得那么远。没有堆栈溢出
l4m2,13

如果有问题n<100,您可以使用O(2^n)解决方案,我想它是可以的,只要它最终使结果重新确定即可
l4m2

1
仅供参考,NaN结果与递归无关-它是阶乘计算的溢出,该乘数计算应在使用浮点数时使用整数(198!永远不会适合int)。
James Holderness

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)。


为什么不做一个片段?
Arjun

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)))

由于pizzapant184节省了6个字节的(-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

OK,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#nwhere x是要计算其余弦的数字,以及n要取的部分和的顺序。


您可以通过删除保存相当多的字节fromIntegral,并使用**替代的^,如
B.梅塔

x#n=sum[(-x*x)**i/product[1..2*i]|i<-[0..n-1]]再节省3个字节。
林恩

3

Pyt37 34 33字节

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

3

J,26 24字节

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

-2个字节,感谢@cole

我最初计划使用循环gerund在加减之间交替,但无法使其正常工作。

说明:

                    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.将研究循环gerund:它可能失败了,因为J /从右到左求值,因此您需要使用|.(或者您可能对此有所考虑,但仍然遇到困难)。
科尔

3

Perl 6、53字节

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

在线尝试!

这实际上计算复指数Ë 的要求条款的两倍数量,然后取实部。


2

带符号数学工具箱的MATLAB,57个字节

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

这定义了一个匿名函数,该函数接受double输入xn并将结果输出为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 144130字节

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

感谢Kevin节省了一些字节!


您可以通过按摩函数定义来节省一些字节:F(m){...}f(x,n)float x;{...}
Kevin

由于u * 1 == u,因此您可以在第一个函数中使用while(m)u*=m--u=m;while(--m)u*=m(相同长度)进行循环
Kevin

i<=n-1i<n
Kevin一样

@Kevin谢谢,您绝对正确,现在已经有一段时间没有打高尔夫球了。:)
Abel Tom



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;

需要XN从命令行参数从命令行参数获取;与-r

循环$i0N*2-1,保持fac($i)$f; 如果$i是偶数,则将总和相加$s。打印总和。


我希望我有复数(以M_I虚数为单位);
我只想乘$fM_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)

建立无限(在有限的意义上,但如果PC有足够的内存,则可以要求建立2 * n个元素的列表)的cos(x)泰勒级数的部分和列表,在'a'中计算,在“ eval( taylor(cos(x)),a)“;获取“。(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

Ĵ,17个字节

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

在线尝试!

使用一个 内置,我认为还可以。

不幸的是,我真的不知道如何与像这样通过curring接受参数的函数一起工作,所以我必须明确地做到这一点。我敢肯定,有一种默契或更短的方法。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.