我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
归档 2013 年 7 月

回到过去,预测未来

“… 预备阶段完成,一分钟后进入时空融合。”,密闭的舱室内,一个科学狂人,花费了毕生精力,造出了一台时间机器,今天他将亲自进行第一次测试。他也不确定会被送到多久以前,但是现在程序已经启动,无法取消了。“四、三、二 …”,眼前一道白光,他屏住了呼吸——然后——“ … 预备阶段完成,一分钟后进入时空融合。”。

时间旅行是个多么诱人的话题,无数的影视和文学作品以此为题。

人们对时间旅行最大的误读恐怕就是“超过光速就能回到未来”。这个推论显然来自相对论中的时间膨胀公式(运动速度越接近光速,该物体时间流逝越慢), 但是这个公式是基于相对论中另一个基本假设“光速是不可超越的”,所以说在写方程的时候标上自变量取值范围是多么地重要。

所谓相对论,提出的基本假设之一就是“时间是相对的”。

当年牛顿的经典力学告诉我们“空间是相对的”,不同的参考系中,观测到的速度是不同的。而现在相对论告诉我们,在不同的参考系中,测量到的时间流逝同样是不同的,时间和速度互相影响着——但所有人都能测量到同样的光速,光速是不可超越的。

根据时间膨胀公式,可以预测的是,当速度足够接近光速的时候,运动物体相对于静止物体时间流逝地更慢,这就是所谓“双生子谬论”。一对双胞胎,如果弟弟以一半的光速运动1年,那么在静止的哥哥看来,实际上已经过去了1.3年,弟弟要比哥哥年轻了0.3岁。

这相当于弟弟只花了1年便到达了1.3年后,实现了当前向未来的时间旅行,如果运动速度更加接近光速,那么这个效应会更加明显,比如如果速度达到99.9%光速,那么运动的1年将相当于静止的50年。

在相对论中,从现在到未来的时间旅行是被允许的,只要你有足够的能量,将你加速到足够接近光速,就可以让你的时间流逝地更慢,从而更快地到达未来。

但根据相对论的质能方程,越接近光速,加速所需要的能量越大,以至于将有质量的物体加速到光速需要无限大的能量,这也是在计算上光速不能被超越的原因。

所以更激动人心的是回到过去。但凡提到这个话题,就必须提到因果关系,不同于向未来旅行,向过去旅行涉及到对已有历史的改变,这种改变超越了大多数人对因果关系的认识,科幻作品也大多是在这个环节(如何克服因果关系)做文章。

对我们而言,时间似乎是天然的一种属性,那么究竟何谓时间?根据热力学第二定律“闭合系统中的无序度(熵)总是在增加”,宇宙的状态总是在由整齐向混乱运动着,这个过程是不可逆的,局部的有序度增加了一点,整体的无序度则增加更多。

这种现象为我们(智慧生命)定义了一个非常有意义的时间箭头,这也和我们的认知相适应:很多过程,比如打碎一个杯子,比如吃一顿饭,都是无法逆转的,你只有把碎玻璃片扔进垃圾桶。这种时间箭头也为我们的生命(自我意识)赋予了意义:如果一切都是由混乱,自动地变为整齐,那么我们的生命还有什么挑战?有什么意义?

这种时间箭头的方向可能是由于宇宙大爆炸的方向,以及各种宇宙常数共同决定,也只有这样的宇宙,才可能存在智慧生命。

为了解决回到过去带来的因果关系问题,有两种较为常见的理论:决定论和平行宇宙。

决定论即宇宙中发生的一切事件,都由宇宙的初始状态和物理定律决定,不为智慧生命的自我意识而改变。一切历史和未来都是事先确定的,如果有人可能回到过去并改变历史,这也是历史早就确定了的。

平行宇宙即,除了我们的宇宙还存在着无数的宇宙,每个宇宙代表着不同的选择,每个选择都对应一个宇宙。回到过去事实上就是到达了另一个平行宇宙,历史将在这里分支。

我个人倾向于决定论,我觉得这才是最简洁,最完美的解释,证明了是物理定律而非自我意识在统治宇宙,我相信这也是大多数物理学家的想法。

而平行宇宙则更多地出现在科幻作品中,可以为情节带来更多戏剧性。

在目前的物理学领域中,回到过去的新的希望是虫洞理论,但直到目前,即使是仅供微观粒子通过的虫洞,也没有被观测到,仅仅存在于理论中,但目前物理学也同样无法否认时间旅行(回到过去)的存在,也许有朝一日会有新的发现。

但是直到目前我们还没有发现来自未来的时间旅行者不是么?开个玩笑。

平行宇宙的假设是各个宇宙之间相互独立,无法互相影响,如果真的是这样,那么根据剃刀原理我们就没有必要去假设平行宇宙模型。而但如果能通过时间旅行到达另外一个宇宙,即说明这些宇宙并非是无关联的。

而决定论中,则很可能出现因果循环,即一段信息,来自未来,却又对未来施加着影响,好像这段信息是凭空出现的一样(可以参见短篇小说《你们这些还魂尸——》), 而根据蝴蝶效应,事实上任何回到过去的行为都会造成因果循环,因此——如果宇宙存在一个确定的历史,那么就不允许有回到过去的时间旅行。

前面我们提到按照决定论,宇宙的历史和未来是确定的,这意味着如果我们掌握了宇宙的全部物理定律(这也是物理学家们正在做的事情),并且知道宇宙任意一刻的状态,那么我们可以随意地计算历史,预测未来,会是这样么?

阻止我们的第一道关卡便是不确定性原理,即粒子的位置和状态(速度)不能被同时确定,但我们可以将位置和速度作为一个整体来看待,这即是量子力学中波函数的概念。

虽然不确定性原理削弱了我们预测未来的能力,但我们仍可以通过波函数进行一定程度的预测。

而第二个障碍是黑洞,黑洞具有极强的引力,以至于光也无法逃脱。黑洞的边缘,即为黑洞的视界,在视界内发生的一切事件将不会对外界造成影响,因为任何影响都不可能超过光速来作用。黑洞将发射仅与其质量相关的辐射,其他的一切信息都会在黑洞消失时被蒸发掉(黑洞无毛理论)。一旦波函数的任意部分掉入黑洞,我们便进一步丧失了对未来的精确预测能力。

总结:

  • 由当前到未来的时间旅行是被相对论允许的
  • 目前仍没有完美的理论能够解释回到过去带来的因果关系问题
  • 目前物理学还没有可靠的可以使宏观物体回到过去的理论
  • 目前物理学还无法否认回到过去的时间旅行的存在
  • 因为不确定性原理的存在,我们不可能精确地预测未来

(开头的段子改写自《史上第一个时间旅行者》).

整理了一下我的博客

本文于 2015.7.14 修订:更新链接地址

在两个多月前,我的博客通过了备案,移到了阿里云的位于青岛的国内服务器,同时使用了新的Nginx+PHP-FPM架构,无论是软件还是硬件(网络)上,都有不少性能提升。

所以是时候提高一下内容质量了,说实话我觉得我的日志一直都保持了相当的高质量,不过也有不少历史遗留问题。

本文可能会被转载到其他地方,比如我的QQ空间和论坛等等,请记住我的博客地址https://jysperm.me, 这里可以取得最佳的阅读效果,同时如果日志中有错误,我通常也只会在这里修改。在Google搜索“精英王子”第一个即是我的博客,百度什么的还是不要用了 …

博客新增了SSL版本, 不过目前多说是不支持SSL的,他们承诺近期支持,不过一直都没有消息。

我重新阅读了我所有的日志,116篇,这个博客是我在上高中时建立的,不过我也在陆续把上高中之前的高质量日志移过来。

我为所有日志重新分了类:

  • 技术:编程方面的日志
  • 生活:以记叙生活和校园为主的日志
  • 随笔:发表胡思乱想的观点的日志

同时我还删去了所有日志的 tag, 之前有无数人吐槽我 tag 加得太泛滥了(好像最多的时候达到了1200个), 重新添加 tag 的标准则吝啬了许多。

再然后,我重写了About Me页面,增加了一个简历页面。

应该说这个博客也算是令我非常自豪的作品之一,每当大家讨论些什么的时候,我可以说这个话题我好久好久以前就写过一篇日志,然后丢出链接——虽然这样很讨人厌的样子。

每篇日志,背后都有一个故事。我可以记起,我在写这篇日志的时候,在做些什么,想些什么;当第一时间发给朋友们时,他们又评论了些什么。

我这可能是我的朋友圈子里写的最长,质量最高的博客了吧。

看着其他人的博客一个个倒闭,我表示非(xìng)常(zāi)惋(lè)惜(huò).

这段时间写的日志挺多的,草稿箱里也有很多写了一半写不下去的,或者写完了觉得不好,没发的,差不多二十多篇。

笔记:函数和栈

从入门编程开始,我们一直在和函数打交道,但直到今天,我才勉强敢谈一谈对函数的认识。

在以C为代表的,绝大多数“正常”的编程语言中,函数都 是组织代码和组成程序的基本单位,甚至在CPU中也内建了对函数(过程)调用的支持。其他所谓面向对象风格 不过是对函数的进一步封装而已。

程序执行时的控制流,也是以函数为基本单位来进行调度的,每一次函数调用,就标志着一次控制流的转移。在经典的模型中,一个函数可以调用包括自己(调用自身的行为被称为递归)在内的任何函数,被调用的函数也可以再调用其他函数。函数间通过参数和返回值来传递信息,前者用于调用者向被调用信息发送信息,后者用于被调用函数向调用者返回信息。

那么我们如何在脑中构建一幅函数间互相调用的景象呢?这里我就不得不提到栈这个概念。栈是最简单最基础的数据结构之一,栈是一种线性的容器,但其特殊之处在于只能从其中一端插入或取出数据,这一端被称为栈顶。这使得栈具有这样的特征:先被插入栈的数据,要最后被取出;后加入栈的数据,将先被取出,即LIFO(Last In First Out, 后进先出).

函数调用存在着类似的性质:在某一时刻的同一调用树(而不是多个并行执行的函数)上,最先被调用的函数将最后被返回,因为它需要等待所有之后被调用的函数返回才行。 于是在计算机中,我们通过栈来维护函数间的调用状态,这种栈,也被称为运行栈,线程栈,函数栈。

栈上为单个函数所分配的区域,被称为栈帧。栈顶由一个栈顶指针来指示,栈顶指针在函数执行时会随时改变,因此还有另外一个帧指针指向当前栈帧的起始处,函数通常通过帧指针来访问数据。栈指针和帧指针被保存在单独的寄存器上。

函数执行时所定义的局部变量都将被分配在栈上,这些局部变量(和函数参数)决定了函数的执行状态。

当函数调用另一个函数时,首先要保存寄存器的值。因为寄存器是被多个函数所共享的自由,为了防止被调函数覆盖寄存器,主调函数必须负责将部分寄存器的值保存在栈上。然后将要传递给被调函数的参数插入栈中,在参数较少的情况下,也可能直接使用寄存器来传递参数。然后再插入下一条指令的地址,即被调函数返回时要返回到的地址。最后将控制权移交到被调函数的首地址。

被调函数开始执行,这也标志着调用者的栈帧已经结束。被调函数首先在栈上保存当前旧的帧指针,然后将帧指针甚至为栈指针减去1,即当前栈帧的第一项是旧的帧指针。 然后被调函数也开始保存寄存器,调用者和被调函数分别负责保存哪些寄存器是有约定的。

然后被调函数开始执行真正的代码,并通过帧指针来访问参数,参数在栈中的顺序是由调用约定决定的。在函数执行的过程中,函数也可能在栈上创建和销毁局部变量,但均遵循栈的后入先出原则。在函数执行即将结束时,将返回值保存在特定的寄存器中。

当被调函数返回时,首先恢复已保存的寄存器的值,然后将帧指针赋值给栈指针,即丢弃当前栈帧除了已保存的旧的帧指针的全部数据。然后从栈恢复旧的帧指针,至此被调函数已经完成了全部清理工作,帧指针指向调用者的栈帧头部,栈指针指向调用者栈帧的尾部。被调函数将控制权移交给当前栈指针指向的返回地址。

现在控制权回到了调用者,调用者首先弹出栈中的返回地址和参数,然后恢复寄存器的值,接着执行剩下的代码,被调函数的返回值在特定的寄存器中。

本文从栈的角度描述了一个函数的执行过程,着重介绍了4个关键的时间点:调用者调用被调函数、被调函数开始执行、被调函数返回前的清理工作、控制权返回到调用者。

可以看到函数的执行和栈的使用本来就是密不可分的。

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2023-12-20.