雷神之锤3是一款九十年代非常经典的游戏,内容画面都相当不错,作者是大名鼎鼎的约翰卡马克。由于当时游戏背景原因,如果想要高效运行游戏优化必须做的非常好,否则普通人的配置性能根本不够用,在这个背景下就诞生了“快速开平方取倒数的算法”。在早前自雷神之锤3的源码公开后,卡马克大神的代码“一战封神”,令人“匪夷所思”的0x5f375a86,引领了一代传奇,源码如下:
相比sqrt()函数,这套算法要快将近4倍,要知道,编译器自带的函数,可是经过严格仔细的汇编优化的啊!
floatQ_rsqrt(floatnumber){longi;floatx2,y;constfloatthreehalfs=1.5F;x2=number*0.5F;y=number;i=*(long*)&y;i=0x5f3759df-(i>>1);//whatthefucky=*(float*)&i;y=y*(threehalfs-(x2*y*y));//1stiteration//y=y*(threehalfs-(x2*y*y));//2nditeration,thiscanberemoved#ifndefQ3_VM#ifdef__linux__assert(!isnan(y));//bk010122-FPE#endif#endifreturny;}当然,更加魔幻的是,普渡大学的数学家ChrisLomont看了以后觉得有趣,但也不服气,决定要研究一下卡马克弄出来的这个猜测值有什么奥秘。
在精心研究之后,Lomont从理论上也推导出一个最佳猜测值,和卡马克的数字非常接近,0x5f37642f。Lomont计算出结果以后非常满意,于是拿自己计算出的起始值和卡马克的神秘数字做比赛,看看谁的数字能够更快更精确的求得平方根。结果是卡马克赢了...
Lomont怒了,采用暴力方法一个数字一个数字试过来,终于找到一个比卡马克数字要好上那么一丁点的数字,虽然实际上这两个数字所产生的结果非常近似,这个暴力得出的数字是0x5f375a86。
当然,Fork炸弹用其它语言也可以分分钟写出来一个,例如,python版:
这个算法是由图灵奖得主东尼·霍尔(C.A.R.Hoare)在1960年提出的,从名字中就可以看出,快速就是他的特点。
快速排序采用了“分治法”策略,把一个序列划分为两个子序列。在待排序列中,选择一个元素作为“基准”(Pivot)。
所有小于“基准”的元素,都移动到“基准”前面,所有大于“基准”的元素,都移动到“基准”后面(相同的数可以到任一边)。此为“分区”(partition)操作。分别对“基准”两边的序列,不断重复一、二步,直至所有子集只剩下一个元素。
假设现有一数列:
对此数列进行快速排序。选择第一个元素45作为第一趟排序的“基准”(基准值可以任意选择)。
第一趟:将元素45拿出来,分别从数列的两端开始探测首先从右向左开始,找到第一个小于45的元素为25,然后将25放置到第一个元素45的位置上。此时数列变为:
然后从左向右开始,找到第一个大于45的元素为66,然后将66放置到原先元素25的位置上。此时数列变为:
继续从右向左开始,找到第二个小于45的元素为10,然后将10放置到原先元素66的位置上,此时数列变为:
继续从左向右开始,找到第二个大于45的元素为90,然后将90放置到原先元素10的位置上,此时数列变为:
继续从右向左开始,此时发现左右碰面,因此将“基准”45放置到原先元素90的位置上,此时数列变为:
至此,第一轮结束,“基准”45左侧为小数区,右侧为大数区。同样的分别对小数区和大数区应用此方法直至完成排序。