牛顿迭代法快速寻找平方根

    下面这种方法可以很有效地求出根号a的近似值:首先随便猜一个近似值x,然后不断令x等于x和a/x的平均数,迭代个六七次后x的值就已经相当精确了。
    例如,我想求根号2等于多少。假如我猜测的结果为4,虽然错的离谱,但你可以看到使用牛顿迭代法后这个值很快就趋近于根号2了:

(       4  + 2/   4     ) / 2 = 2.25
(    2.25  + 2/   2.25  ) / 2 = 1.56944..
( 1.56944..+ 2/1.56944..) / 2 = 1.42189..
( 1.42189..+ 2/1.42189..) / 2 = 1.41423..

….

      
    这种算法的原理很简单,我们仅仅是不断用(x,f(x))的切线来逼近方程x^2-a=0的根。根号a实际上就是x^2-a=0的一个正实根,这个函数的导数是2x。也就是说,函数上任一点(x,f(x))处的切线斜率是2x。那么,x-f(x)/(2x)就是一个比x更接近的近似值。代入f(x)=x^2-a得到x-(x^2-a)/(2x),也就是(x+a/x)/2。
    同样的方法可以用在其它的近似值计算中。Quake III的源码中有一段非常牛B的开方取倒函数。

函数上某一点导数为正,该点邻域不一定形成单增区间

    给出一个连续函数,某一点上的导数为正说明函数在这一点是上升的,换句话说函数从左边充分靠近该点时函数值总小于这个点,从右边靠近该点时函数值总大于这个点。但这并不等于说这一点左右是一个单增区间,也就是说该点左右任意小的邻域内函数都不是单调递增的。你能找出这样的函数来吗?

    昨天数学课上,我学到了一个比较牛B的东西:函数上某一点导数为正,该点邻域不一定形成单增区间。虽然左边的点都比该点低,右边的点都比该点高,但这并不能说明左边和右边各自都是单增的。这样的函数确实存在,而且并不是那种很怪的函数,仅仅是一个简单的初等函数:f(x) = x + 2x^2*sin(1/x)。由于x=0时函数没有定义,我们规定f(0)=0。按照导数的定义,函数在x=0时的导数值为
   Limit[ (f(0+Δx)-f(0))/(Δx-0), Δx->0 ]
= Limit[ f(Δx)/Δx, Δx->0 ]
= Limit[ 1 + 2Δx*sin(1/Δx) , Δx->0 ]
= 1

    这说明函数在x=0处的导数确实是正的。当x≠0时,按照求导法则可以求出f'(x) = 1 – 2*cos(1/x) + 4x*sin(1/x)。当|x|充分小时,最后一项可以忽略不计;此时只要1/x恰好等于2πn (n为整数),那么f'(x)保证是负的。这就告诉我们,x=0左右任意近的位置都存在导数为负的情况,这样不管邻域范围多小总能找到一个函数值在减小的地方。
    其实,看一下f(x)的函数图象,你会立即明白这是怎么回事。这个函数越接近原点抖动频率越快(到原点时“周期”无限小),同时振幅也越小(到原点时振幅为0,这样可以保证导数存在);但这个函数总的来说呈上升趋势。因此,这个函数才有我们前面提到的奇怪性质。

OI/MO必备:巨牛无比的公式、定理速查表

    数学考试时我最怕的就是三角函数,几十个公式我一个都背不到。那时我有了制作公式定理表的想法。经过反复尝试,我那张表已经设计得非常合理了,表里的内容也初具规模。我复印了几份给我的几个同学,反映都还不错,其它的同学听说了都想来找我要一份。当初我以为我那张表已经很牛了,今天终于发现我错了。
    刚才偶然发现一份非常牛的公式定理表,满满写了10页,不但包含有完整的三角公式、微分表、积分表,还有排列组合公式、概率公式、质数表、杨辉三角等等,甚至还有主定理、图论概念等东西。想要公式定理手册的OI/MO牛不用再去买中学数理化的口袋书了,你真正需要的东西那上面根本没有;这10页的速查表才是真正为你设计的,打印一份随身携带更能体现你nerd/geek的身份……
    点击这里下载(pdf, 154KB) 请勿直接链接到此文件

神奇的分形艺术(二):一条连续的曲线可以填满整个平面

    虽然有些东西似乎是显然的,但一个完整的定义仍然很有必要。比如,大多数人并不知道函数的连续性是怎么定义的,虽然大家一直在用。有人可能会说,函数是不是连续的一看就知道了嘛,需要定义么。事实上,如果没有严格的定义,你很难把下面两个问题说清楚。
    你知道吗,除了常函数之外还存在其它没有最小正周期的周期函数。考虑一个这样的函数:它的定义域为全体实数,当x为有理数时f(x)=1,当x为无理数时f(x)=0。显然,任何有理数都是这个函数的一个最小正周期,因为一个有理数加有理数还是有理数,而一个无理数加有理数仍然是无理数。因此,该函数的最小正周期可以任意小。如果非要画出它的图象,大致看上去就是两根直线。请问这个函数是连续函数吗?如果把这个函数改一下,当x为无理数时f(x)=0,当x为有理数时f(x)=x,那新的函数是连续函数吗?
    Cauchy定义专门用来解决这一类问题,它严格地定义了函数的连续性。Cauchy定义是说,函数f在x=c处连续当且仅当对于一个任意小的正数ε,你总能找到一个正数δ使得对于定义域上的所有满足c-δ< x <c+δ的x都有f(c)-ε<f(x)<f(c)+ε。直观地说,如果函数上有一点P,对于任意小的ε,P点左右一定范围内的点与P的纵坐标之差均小于ε,那么函数在P点处连续。这样就保证了P点两旁的点与P无限接近,也就是我们常说的“连续”。这又被称作为Epsilon-Delta定义,可以写成“ε-δ定义”。
    有了Cauchy定义,回过头来看前面的问题,我们可以推出:第一个函数在任何一点都不连续,因为当ε< 1时,δ范围内总存在至少一个点跳出了ε的范围;第二个函数只在x=0处是连续的,因为此时不管ε是多少,只需要δ比ε小一点就可以满足ε-δ定义了。
    在拓扑学中,也有类似于ε-δ的连续性定义。假如一个函数f(t)对应空间中的点,对于任意小的正数ε,总能找到一个δ使得定义域(t-δ,t+δ)对应的所有点与f(t)的距离都不超过ε,那么我们就说f(t)所对应的曲线在点f(t)处连续。

    回到我们的话题,如何构造一条曲线使得它可以填满整个平面。在这里我们仅仅说明存在一条填满单位正方形的曲线就够了,因为将此单位正方形平铺在平面上就可以得到填满整个平面的曲线。大多数人可能会想到下面这种构造方法:先画一条单位长的曲线,然后把它变成一个几字形,接着把每一条水平的小横线段变成一个几字形,然后不断迭代下去,最后得到的图形一定可以填满整个单位正方形。我们甚至可以递归地定义出一个描述此图形的函数:将定义域平均分成五份,第二和第四份对应两条竖直线段上的点,并继续对剩下的三个区间重复进行这种操作。这个函数虽然分布得有些“不均匀”,但它确实是一个合法的函数。最后的图形显然可以填充一个正方形,但它是不是一条曲线我们还不知道呢。稍作分析你会发现这条“曲线”根本不符合前面所说的ε-δ定义,考虑任何一个可以无限细分的地方(比如x=1/2处),只要ε<1/2,δ再小其范围内也有一条竖线捅破ε的界线。这就好像当n趋于无穷时sin(nx)根本不是一条确定的曲线一样,因为某个特定的函数值根本不能汇聚到一点。考虑到这一点,我们能想到的很多可以填满平面的“曲线”都不是真正意义上的连续曲线。为了避免这样的情况出现,这条曲线必须“先把自己周围填满再延伸出去”,而填满自己周围前又必须先填满“更小规模的周围”。这让我们联想到分形图形。

    德国数学家David Hilbert发现了这样一种可以填满整个单位正方形的分形曲线,他称它为Hilbert曲线。我们来看一看这条曲线是怎么构造出来的。首先,我们把一个正方形分割为4个小正方形,然后从左下角的那个小正方形开始,画一条线经过所有小正方形,最后到达右下角。现在,我们把这个正方形分成16个小正方形,目标同样是从左下角出发遍历所有的格子最后到达右下角。而在这之前我们已经得到了一个2×2方格的遍历方法,我们正好可以用它。把两个2×2的格子原封不动地放在上面两排,右旋90度放在左下,左旋90度放在右下,然后再补三条线段把它们连起来。现在我们得到了一种从左下到右下遍历4×4方格的方法,而这又可以用于更大规模的图形中。用刚才的方法把四个4×4的方格放到8×8的方格中,我们就得到了一条经过所有64个小方格的曲线。不断地这样做下去,无限多次地迭代后,每个方格都变得无穷小,最后的图形显然经过了方格上所有的点,它就是我们所说的Hilbert曲线。下图是一个迭代了n多次后的图形,大致上反映出Hilbert曲线的样子。
        

    根据上面这种方法,我们可以构造出函数f(t)使它能映射到单位正方形中的所有点。Hilbert曲线首先经过单位正方形左下1/4的所有点,然后顺势北上,东征到右上角,最后到达东南方的1/4正方形,其中的每一个阶段都是一个边长缩小了一半的“小Hilbert曲线”。函数f(t)也如此定义:[0,1/4]对应左下角的小正方形中所有的点,[1/4,1/2]就对应左上角,依此类推。每个区间继续划分为四份,依次对应面积为1/16的正方形,并无限制地这么细分下去。注意这里的定义域划分都是闭区间的形式,这并不会发生冲突,因为所有m/4^n处的点都是两个小Hilbert曲线的“交接处”。比如那个f(1/4)点就是左上左下两块1/4正方形共有的,即单位正方形正左边的那一点。这个函数是一条根正苗红的连续曲线,完全符合ε-δ定义,因为f(t-δ)和f(t+δ)显然都在f(t)的周围。
    Hilbert曲线是一条经典的分形曲线。它违背了很多常理。比如,把Hilbert曲线平铺在整个平面上,它就成了一条填满整个平面的曲线。两条Hilbert曲线对接可以形成一个封闭曲线,而这个封闭曲线竟然没有内部空间。回想我们上次介绍的Hausdorff维度,你会发现这条曲线是二维的,因为它包含自身4份,每一份的一维大小都是原来的一半,因此维度等于log(4)/log(2)。这再一次说明了它可以填满整个平面。

    Hilbert曲线的价值在于建立一维空间与二维空间一一对应的关系。Hilbert曲线可以看作是一个一维空间到二维空间的映射,也就是说我们证明了直线上的点和平面上的点一样多(集合的势相同)。Hilbert曲线也是一种遍历二维格点的方法,它同样可以用来证明自然数和有理数一样多。如果你已经知道此结论的Cantor证明,你会立刻明白Hilbert遍历法的证明,这里就不再多说了。当然,Hilbert曲线也可以扩展到三维空间,甚至更高维的空间,从而建立一维到任意多维的映射关系。下图就是一个三维Hilbert曲线(在迭代