Long Luo's Life Notes

每一天都是奇迹

By Long Luo

任何一款科学计算器上都可以计算三角函数,三角函数应用于生活工作中的方方面面,但计算机是如何计算三角函数值的呢?

三角函数本质上是直角三角形的3条边的比例关系,计算并没有很直观,那么计算机是如何计算三角函数值的呢?

在微积分中我们学习过 泰勒公式 ,我们知道可以使用泰勒展开式来对某个值求得其近似值,例如:

\[ \sin \angle 18^{\circ} = \frac{\sqrt {5} - 1}{4} \approx 0.3090169943 \]

利用泰勒公式,取前 \(4\) 项:

\[ \sin x \approx x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} \]

代入可得:

\[ \sin \angle 18^{\circ} = \sin \frac{\pi}{10} = \frac{\pi}{10} - \frac{1}{6} (\frac{\pi}{10})^3 + \frac{1}{120} (\frac{\pi}{10})^5 - \frac{1}{5040} (\frac{\pi}{10})^7 \approx 0.30903399538 \]

可见取前 \(4\) 项时精度已经在 \(10^{-5}\) 之下,对于很多场合精度已经足够高了。

在没有了解 CORDIC(Coordinate Rotation Digital Computer) Algorithm 1 算法之前,我一直以为计算器是利用泰勒公式去求解,最近才了解到原来在计算机中,CORDIC 算法远比泰勒公式高效。

下面我们就来了解下泰勒公式的不足之处和 CORDIC 算法是怎么做的。

泰勒公式的缺点

上一节我们使用泰勒公式去计算三角函数值时,需要做很多次乘法运算,而计算器中乘法运算是很昂贵的,其缺点如下所示:

  1. 展开过小则会导致展开精度不够,展开过大则会导致计算量过大;
  2. 幂运算需要使用乘法器,存在很多重复计算;
  3. 需要很多变量来存储中间值。

在之前的文章 矩阵乘法的 Strassen 算法 ,就是通过减少乘法,多做加法,从而大大降低了运算量,那么我们可以用相同的思想来优化运算吗?

当然可以,让我们请出今天的主角:CORDIC 算法

阅读全文 »

By Long Luo

最近在书店里看到一本 《数学的奥秘》 ,原著是 《The Secret Life of Equations: The 50 Greatest Equations and How They Work》 ,讲的是最伟大的数学方程式起源、构成、含义和应用。书的内容并不多,我看了其中的一部分,里面有讲 墨卡托投影( \(\textit{Mercator projection}\) )1

我对地理和地图一直很感兴趣,但之前对原理一直一知半解的,只知道我们常见的地图都是墨卡托投影,由墨卡托( \(\textit{Gerardus Mercator}\) )2 在 1569年创立。但墨卡托投影的原理是什么却并不清楚。书里面只有几页,但具体公式缺乏说明及推导过程,所以这几天通过查找资料掌握了墨卡托投影的原理。

如何绘制地图?

在大航海时代,航海家可以通过六分仪和观察日月星辰获取到经纬度,但在茫茫大海中迷失方向是很可怕的事情,如何才能正确的航行到目的地呢?

地球由于自转是一个两极比赤道略短的扁球体,但扁率约为 \(\dfrac {1}{300}\) ,非常之低,因为可以视为球体。因为球面不是可展曲面,也就是如果展成平面的话,长度会发生形变,所以也会形变。因为根据高斯绝妙定理 ( \(\textit{Theorema Egregium}\) )3 ,平面的高斯曲率为 \(0\) ,而球面的高斯曲率为 \(\dfrac {1}{R^2}\) ,其中 \(R\) 为球面半径,所以在保持图形完整性前提下,将球面转化为平面,投影后得到的经纬线网形状必然会产生变形,也就是说,在投影的过程中,变形是必然存在的。

在这种情况下,墨卡托运用等角圆柱投影法绘制了航海图,极大地方便了航海家。有了墨卡托海图,航海家想要到达某个目的地,只需要在出发点和目的地之间连一条直线,量出这条航线和经线的夹角,按照航行路线就能到达目的地。

图1. 地图的墨卡托投影

什么是墨卡托投影?

设想将地球置于在一中空的圆柱里,如下图所示,其基准纬线(赤道)与圆柱相切。再设想地球中心处放置一灯泡,那么从球心处发射的光线会把球面上的图形投影到圆柱体上,之后再将把圆柱体展开,那么就可以得到一张墨卡托投影绘制出的地图。

阅读全文 »

By Long Luo

PID 算法 s是自动控制领域中很重要的算法。

\[ u(t) = K_Pe(t) + K_I \int e(t) \mathrm{d}t + K_D \frac{\mathrm{d}e(t)}{\mathrm{d}t} \]

Simple PID Controller

非常简单的 PID 算法在线互动式模拟器,传送门 →

PID Algorithm

之前这个是 PID v1.0 版本,最近重构了代码,增加了一些新功能:

  1. 增加机器人速度 \(v\) 及加速度 \(a\) 显示;
  2. 增加 2 个图表展示 PID X 轴方向及 Y 轴方向的 P、I、D \(3\) 个分量随时间变化显示;
  3. 之前代码将时间及速度固定了,但这不符合实际,增加随 \(dt\) 变化积分和微分项;

pid_track

阅读全文 »

By Long Luo

在数学、物理学、工程和计算机领域中,泰勒公式1 是一种广泛使用的分析方法,用来计算函数的近似值。在实践中,很多函数非常复杂,而且某些函数是不可积的,想求其某点的值,直接求无法实现。

泰勒公式可以将复杂的函数近似地表达为简单的多项式函数,用一个多项式函数去逼近一个给定的函数(即尽量使多项式函数图像拟合给定的函数图像)。注意在逼近的时候一定是从函数图像上的某个点展开。

下图所示就是不同项数的泰勒公式对 \(\sin x\) 的逼近:

图1. 泰勒公式对 \sin 的逼近

泰勒级数的定义为:

\[ f(x) = \sum _{n=0}^{\infty}{\frac{f^{(n)}(a)}{n!}}(x-a)^{n} = f(a) + {\frac {f'(a)}{1!}}(x - a) + {\frac {f''(a)}{2!}}(x - a)^{2} + {\frac {f'''(a)}{3!}}(x - a)^{3} + \cdots \]

这里,\(n!\) 表示 \(n\) 的阶乘,而 \(f^{(n)}(a)\) 表示函数 \(f\) 在点 \(a\) 处的 \(n\) 阶导数。如果 \(a = 0\) ,这个级数也被称为麦克劳林级数(Maclaurin series)2

泰勒展开式有很多,那么如何记忆呢?首先我们需要明白,泰勒公式之间都是有相互关联的,我们可以通过推导来理解性记忆这些公式。泰勒公式的具体推导过程可以参考数学分析教材或者网络3

下面我们就推导这些公式,以便更好的记忆4

几何级数 Geometric series

对于 \(-1 < x < 1\) 的情况,几何级数5 由等比数列求和公式可得:

\[ \frac{1}{1 - x} = \sum _{n=0}^{\infty}x^{n} = 1 + x + x^{2} + \cdots + x^{n} \]

\(-x\) 代入 \(x\) 上式,则:

\[ \frac{1}{1 + x} = \sum _{n=0}^{\infty}(-1)^nx^{n} = 1 - x + x^{2} - x^3 + \cdots + (-1)^n x^{n} \]

\(x^2\) 替代 \(x\) , 由于 \(\arctan x = \int_{0}^{x} \frac{1}{1 + x^2} \mathrm{d}x\) ,对于 \(-1 \le x \le 1, x \neq \pm i\)

\[ \arctan x = \sum _{n=0}^{\infty }{\frac {(-1)^{n}}{2n + 1}}x^{2n + 1} = x - {\frac {x^3}{3}} + {\frac {x^5}{5}} - \cdots + \frac{(-1)^n}{2n + 1}x^{2n + 1} \]

因为 \(\frac{1}{(1 - x)^2} = (\frac{1}{1 - x})'\) ,则:

\[ \begin{aligned} \frac {1}{(1-x)^2} &= \sum _{n=1}^{\infty }n x^{n-1} \\ &= 1 + 2x + 3x^2 + \cdots + n x^{n-1} \end{aligned} \]

\(\frac{1}{(1 - x)^3} = \frac{1}{2} (\frac{1}{(1 - x)^2})'\) ,则有:

\[ \frac {1}{(1 - x)^3} = \sum _{n=2}^{\infty }{\frac {n(n - 1)}{2}}x^{n - 2} \]

指数函数 Exponent function

由于 \(\frac{\mathrm{d} e^x}{\mathrm{d} x} = e^x\)\(e^0 = 1\) 那么:

\[ e^x = \sum _{n=0}^{\infty }{\frac{x^n}{n!}} = 1 + x + {\frac{x^2}{2!}} + {\frac {x^3}{3!}} + \cdots + {\frac{x^n}{n!}} \]

很明显:

\[ \begin{aligned} (e^x)' &= (\frac{1}{0!}+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+\cdots)' \\ e^x &= 0+1+\frac{x}{1}+\frac{x^2}{2!}+\frac{x^3}{3!}\cdots \\ &= 1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\cdots \end{aligned} \]

对于普通指数函数 \(a^x\) , 由于 \(a^x=e^{x\ln a}\) ,如果将 \(x\) 换为 \(x\ln a\) ,那么 \(a^x\) 的泰勒展开式:

\[ \begin{aligned} a^x &= e^{x \ln a} \\ &= 1 + x \ln a + \frac{(x \ln a)^2}{2!} + \frac{(x \ln a)^3}{3!} + \cdots + \frac{(x \ln a)^n}{n!} \\ \end{aligned} \]

阅读全文 »
0%