Tupper自我指涉公式:图象里竟然包含式子本身

    你认为,一个函数图象里是否有可能包含这个函数本身的“图象”?难以置信的是,还真有人构造了这样一个东西。2001年,Jeff Tupper发表的一篇论文里提到了这样一个有趣的不等式:
  
    在0 <= x <= 105,n <= y <= n + 16的范围内,这个不等式对应的图象是这个样子:
  

其中,n = 96093937991895888497167296212785275471500433966012930665150551927170280239526642
46896428421743507181212671537827706233559932372808741443078913259639413377234878
57735749823926629715517173716995165232890538221612403238855866184013235585136048
82869333790249145422928866708109618449609170518345406782773155170540538162738096
76025656250169814820834187831638491155902256100036523513703438744618483787372381
98224849863465033159410054974700593138339226497249461751545728366702369745461014
655997933798537483143786841806593422227898388722980000748404719

    你会觉得这个很神奇吗?你也许会想,天哪,这个是怎么构造出来的啊!但仔细思考之后,你会发现这个一点都不神奇。事实上明白了道理之后你可以构造出无数个这样的式子来。现在给你一些时间让你思考一下,你能否看出其中的奥秘?

    就像魔术揭秘一样,说穿了真相后上面的这些东西就一点意思都没有了。在这个式子里,涉及到x和y的变量时都加上了取整符号,因此整个图象都是一格一格的。这样,不等式右边的式子就简化为y div 17 * 2^(-17x – y mod 17) mod 2,其中x和y都为整数。接着观察,一个数乘以2的负k次方相当于对应的二进制数右移k位,那么x * 2^(-k) mod 2实质上就是二进制数x右起第k位上的数字。对于某个自然数t,当17t <= y < 17(t+1)时,指数-17x – y mod 17恰好对应所有的负整数,于是位于y=17t和y=17t+16之间的图象的每个像素和t的二进制中的每一位数字一一对应。随着t值的增加,图形的像素会一点一点地变化。当纵坐标足够大时,必然会出现一段高度为17的图象,图象的样子和不等式本身的样子相同。当然,你也可以在里面“找到”任何你想要的图象,只需要把图象还原为二进制数并转换为十进制即可。你甚至可以告诉你的MM,说你发现了一个函数,函数在某个位置的图象正好是某某某我爱你的字样。

Matrix67原创
转贴请注明出处
最近发现了一些很不厚道的人,希望大家注意哦!

趣题:单位正方形内相互分离的两个小正方形,其边长和小于1

  
    有人问到我这篇日志里的相关问题,这里简单说一下。
    1941年,数学家Paul Erdős在American Mathematical Monthly上提出了这样一个问题:如果两个正方形S1和S2包容于单位正方形中,它们没有公共点,则它们的边长之和小于1。
    这是一个非常有趣的问题。它有趣的地方就在于,乍看之下想要证明它似乎很困难,然而事实上整个证明过程非常巧妙,初中平面几何知识就可以全部搞定。

  
    如果两个正方形是完全分离的,那么一定能找出一条线可以从它们中间穿过(图上用红色标注)。假设它和另一个方向上的对角线相交于P,从P点出发向单位正方形的四条边分别做垂线。注意到,所有包含于直角三角形内的正方形中,内接于三角形且其中一个顶点在三角形直角顶点上的那个正方形面积最大。于是,蓝色的正方形面积不会超过正方形AMPN的面积,紫色的正方形面积不会超过正方形PSCT的面积,且等号不能同时成立。这就告诉我们,蓝色正方形的边长不超过AN,紫色正方形的边长不超过SC,也即两个正方形的边长和小于单位长度。

Geek的桌面怪物:脑袋跟着你转动的龙

    MM的书桌上往往会放上一些可爱的小玩意儿来点缀一下,那男生的书桌上应该放些什么东西呢?答案是:一个能带给人错觉的手工制作。这是很早以前就在网上流行的手工制作,做出来的东西可以带给人一种奇特的视觉效果,被很多Blogger誉为有史以来“最酷的错觉”。我很早就想尝试一下,但一直懒得花钱出去彩印。昨天买了一台打印机,第一件事就是把保留了很久的制作图纸打印出来。
    做好后,把它放在一个固定的位置,然后不断移动观察点,从不同的角度去看那条龙。你会发现,龙的脑袋竟然会跟着你转动!当然,这只是一个错觉。这条龙完全是纸制的,不可能自己转动。刚才有人说视频不清晰,现在更换视频版本:

    想自己动手做一个吗?制作方法非常简单。把下面的图片打印出来,贴在硬纸板上,然后按照图纸上的提示进行操作。特别注意一下头部的折叠方向,图纸上没有写错,请严格按照图纸上的标注进行操作。下面这些小技巧可以增强视觉效果:站在远处,闭上一直眼;避免光源集中,最好在自然光线下进行观察。
    图片地址:http://www.matrix67.com/blogimage/200708262.jpg

神奇的分形艺术(四):Julia集和Mandelbrot集

    考虑函数f(z)=z^2-0.75。固定z0的值后,我们可以通过不断地迭代算出一系列的z值:z1=f(z0), z2=f(z1), z3=f(z2), …。比如,当z0 = 1时,我们可以依次迭代出:

z1 = f(1.0) = 1.0^2 – 0.75 = 0.25
z2 = f(0.25) = 0.25^2 – 0.75 = -0.6875
z3 = f(-0.6875) = (-0.6875)^2 – 0.75 = -0.2773
z4 = f(-0.2773) = (-0.2773)^2 – 0.75 = -0.6731
z5 = f(-0.6731) = (-0.6731)^2 – 0.75 = -0.2970

    可以看出,z值始终在某一范围内,并将最终收敛到某一个值上。
    但当z0=2时,情况就不一样了。几次迭代后我们将立即发现z值最终会趋于无穷大:

z1 = f(2.0) = (2.0)^2 – 0.75 = 3.25
z2 = f(3.25) = (3.25)^2 – 0.75 = 9.8125
z3 = f(9.8125) = (9.8125)^2 – 0.75 = 95.535
z4 = f(95.535) = (95.535)^2 – 0.75 = 9126.2
z5 = f(9126.2) = (9126.2)^2 – 0.75 = 83287819.2

    经过计算,我们可以得到如下结论:当z0属于[-1.5, 1.5]时,z值始终不会超出某个范围;而当z0小于-1.5或大于1.5后,z值最终将趋于无穷。
    现在,我们把这个函数扩展到整个复数范围。对于复数z0=x+iy,取不同的x值和y值,函数迭代的结果不一样:对于有些z0,函数值约束在某一范围内;而对于另一些z0,函数值则发散到无穷。由于复数对应平面上的点,因此我们可以用一个平面图形来表示,对于哪些z0函数值最终趋于无穷,对于哪些z0函数值最终不会趋于无穷。我们用深灰色表示不会使函数值趋于无穷的z0;对于其它的z0,我们用不同的颜色来区别不同的发散速度。由于当某个时候|z|>2时,函数值一定发散,因此这里定义发散速度为:使|z|大于2的迭代次数越少,则发散速度越快。这个图形可以编程画出。和上次一样,我用Pascal语言,因为我不会C的图形操作。某个MM要过生日了,我把这个自己编程画的图片送给她^_^

{$ASSERTIONS+}

uses graph;

type
   complex=record
      re:real;
      im:real;
   end;

operator * (a:complex; b:complex) c:complex;
begin
   c.re := a.re*b.re - a.im*b.im;
   c.im := a.im*b.re + a.re*b.im;
end;

operator + (a:complex; b:complex) c:complex;
begin
   c.re := a.re + b.re;
   c.im := a.im + b.im;
end;

var
   z,c:complex;
   gd,gm,i,j,k:integer;
begin
   gd:=D8bit;
   gm:=m640x480;
   InitGraph(gd,gm,'');
   Assert(graphResult=grOk);

   c.re:=-0.75;
   c.im:=0;
   for i:=-300 to 300 do
   for j:=-200 to 200 do
   begin
      z.re:=i/200;
      z.im:=j/200;
      for k:=0 to 200 do
      begin
         if sqrt(z.re*z.re + z.im*z.im) >2 then break
         else z:=(z*z)+c;
      end;
      PutPixel(i+300,j+200,k)
   end;

   readln;
   CloseGraph;
end.

    代码在Windows XP SP2,FPC 2.0下通过编译,麻烦大家帮忙报告一下程序运行是否正常(上次有人告诉我说我写的绘图程序不能编译)。在我这里,程序运行的结果如下:

    这个美丽的分形图形表现的就是f(z)=z^2-0.75时的Julia集。考虑复数函数f(z)=z^2+c,不同的复数c对应着不同的Julia集。也就是说,每取一个不同的c你都能得到一个不同的Julia集分形图形,并且令人吃惊的是每一个分形图形都是那么美丽。下面的六幅图片是取不同的c值得到的分形图形。你可能不相信这样一个简单的构造法则可以生成这么美丽的图形,这没什么,你可以改变上面程序代码中c变量的值来亲自验证。

c = 0.45, -0.1428
  

c = 0.285, 0.01
  

c = 0.285, 0
  

c = -0.8, 0.156
  

c = -0.835, -0.2321
  

c = -0.70176, -0.3842
  

    类似地,我们固定z0=0,那么对于不同的复数c,函数的迭代结果也不同。由于复数c对应平面上的点,因此我们可以用一个平面图形来表示,对于某个复数c,函数f(z)=z^2+c从z0=0开始迭代是否会发散到无穷。我们同样用不同颜色来表示不同的发散速度,最后得出的就是Mandelbrot集分形图形:
    

    前面说过,分形图形是可以无限递归下去的,它的复杂度不随尺度减小而消失。Mandelbrot集的神奇之处就在于,你可以对这个分形图形不断放大,不同的尺度下你所看到的景象可能完全不同。放大到一定时候,你可以看到更小规模的Mandelbrot集,这证明Mandelbrot集是自相似的。下面的15幅图演示了Mandelbrot集的一个放大过程,你可以在这个过程中看到不同样式的分形图形。

网上可以找到很多小程序实现Mandelbrot集的放大过程。把上面给出的代码改一改,你也可以写出一个这样的程序来。

Update:2011 年 8 月 31 日,我对这个话题做了更进一步的讨论 http://www.matrix67.com/blog/archives/4570