三角函数计算器(【算法趣谈】计算机是如何计算三角函数的?)

三角函数计算器

????在数学必修四中有很多方法求一个未知角的三角函数,比如说正弦定理、余弦定理等等一系列公式。对一些奇怪的角度,需要我们花很多时间才能通过那些特殊的已知角来算出。????而后来,我们接触到了图形计算器。它可以直接算出一个任意角的三角函数值。这不禁令人感叹:因为任何一个计算机可实现的东西,就意味着是一个公式化的事情:并不需要特殊角的判断,只需要一定量的计算就可以实现。既然如此,那么求一个三角函数值是否也有相对应的公式化操作呢?? ??我们可以这么想:一天,你的好朋友站在一条笔直的赛道的起点。这时他向前跑一段任意的距离x,而在跑的过程中,他的速度是一直变化的,而你并不知道他的变化规律。你只知道,在他起跑时,他的加速度、加速度的加速度、加速度的加速度的加速度(以此类推,相当于速度的n阶导数)。现在,需要你根据这些加速度求出他在x位置的速度。????等等——这和求三角函数有什么关系?!这么说,假设你朋友瞬时速度和其位置的关系是个cos()函数,那么求出朋友在x的瞬时速度,就相当于求出cos(x)的值。只要有办法通过cos(x)在起始点x=0的n阶导数来,也就是他在起点的加速度、加速度的加速度等等,求出他他在x位置的瞬时速度,就能求出cos(x)的函数值!????那么,该怎么求呢?这就用到了麦克劳林展开(Maclaurin Series),也是著名的泰勒展开的特殊形式。麦克劳林展开,就是把一个原本普通的非多项式函数(例如三角函数cos(x))变成多项式形式,也就是很多东西累加的和。而这些多项式中的每一项,正巧就包含了被展开函数在x=0上的各阶导数。换句话说,只要能求出x=0上的函数的各阶导数,就能估计出原来的函数值。其展开公式如下:????? ?????????这样的话,求cos(x)函数值的方法就出现了,我们只需要求出cos(0)的一阶导、二阶导,以此类推,就能用计算机,通过上面的公式求和,来求出f(x)的值。????但是出现了一个问题,就是计算机并不太会求一个函数的导数。但是好在我们可以求啊。不妨算几阶cos(0)的导数,就能看出来规律:cos(0)的n阶导,其实就是一个1,0,-1,0的循环。于是,就可以把上面的公式化简成这个样子:????????因为乘方和阶乘都是计算机支持的操作。这样就可以通过循环来求cosx的值了。????这里我用了python来编写程序,因为其精度高。值得注意的是,如果输入要求的角度是角度制的,记得转换为弧度制。因为上述展开式是按照弧度制计算的。a = eval(input()) # 要计算的角度(角度制)pi = 3.1415926535x = a / 180 * pi # 转换为弧度制sum = 1 # 计算级数的和flag = 1 # cos麦克劳林展开的-1那一项fac = 1 # 计算阶乘pro = 1 # 计算x的2n次方for i in range(1,70): flag *= -1 # 和上一项变号 fac *= (2*i-1)*(2*i) # 上一项的阶乘乘上最近的这两项就是这一项的阶乘 pro *= x*x # 更新乘方 sum += flag * pro / fac # 更新sum值print(sum)?#?输出????????我们来随便试个角度,比如19.260817°????十分精确地计算出来了。????其实,还遗留了一个问题,就是我刚才的程序知识计算了这个展开式的前70项,而实际上n应该是趋近于无限的,也就是cos(19.260817)的值是一个无限小数。因此,程序需要保留精度。既然这样,那么该如何控制所需要保留的精度呢?????这就涉及到了下一个定理:交替级数估值定理(Alternating Series Estimation Theorem)其定理内容是:对于一个每一项都在变小的交替级数,其前n项和,与实际值的差,一定小于第n+1项的绝对值。????比如说刚才那个cos函数,我计算了前70项的和,而这个和和真正的cos(19.260817°)的差,一定小于x的140次方除以140阶乘的绝对值,这个值一定很小很小,因为19.260817转化为弧度制小于1,其140次方就更小,再除以140!这样一个巨大无比的数,其误差寥寥无几。????当然,如果只想输出一个特定的精度,比如保留四位小数,可以给程序加个特判:a = eval(input()) # 要计算的角度(角度制)pi = 3.1415926535x = a / 180 * pi # 转换为弧度制sum = 1 # 计算级数的和flag = 1 # cos麦克劳林展开的-1那一项fac = 1 # 计算阶乘pro = 1 # 计算x的2n次方for i in range(1,70): flag *= -1 # 和上一项变号 fac *= (2*i-1)*(2*i) # 上一项的阶乘乘上最近的这两项就是这一项的阶乘 pro *= x*x # 更新乘方 ai = flag * pro / fac sum += ai# 更新sum值 if ai <= 0.00001: breakprint(sum)?#?输出????好了,本期推文就到这里了。如果觉得有意思的话,别忘了点一下 在看、赞、关注,一键三连哦!

三角函数计算器相关文章


为您推荐