天天看点

开方的几种写法

1.牛顿迭代

假设方程 在  附近有一个根,那么根据f(x)在x0附近的值和斜率,就能估计f(x)和x轴的交点用。迭代式子: 依次计算、、、……,那么序列将无限逼近方程的根。
用牛顿迭代法开平方】令: 所以f(x)的一次导是: 牛顿迭代式: 随便一个迭代的初始值,例如,代入上面的式子迭代。例如计算,即a=2。 …… 计算器上可给出

根据果壳文章以上阐述,由此我们可以写出如下代码:

求9的平方根,尝试 : 3次 , point : 3 , point的平方 : 9 , point平方与target的差值 : 0

到此为此,似乎问题已经得到了圆满的答案,但紧接着我就发现了更有趣的解法

2.魔法数开方倒数

暴雪是一家神奇的公司,它的代码总是能给人惊喜,例如 One-way Hash 被业内赞为最优秀的hash表改良算法(timer33算法应该才是最快的,One-way Hash 在Timer33的基础上改用两次Hash计算来比对Key是否一致,在数据结构没有根本变化的情况下,理论上来说应该更慢)。

下面是暴雪的开平方算法源码,它对上述的牛顿迭代做了一些改进:

这个算法的牛逼之处在于,经典的牛顿迭代里猜测值是随便取的一个值,而这段代码里却用了一个魔法数0x5f3759df来作为猜测值。这个算法只用了一次位运算,根本没有多次迭代就得到了结果,比直接用sqrt(n)快了大约四倍。

但是,我要说但是了,这个算法并不是暴雪原创的。它更早的时候出现在 雷神之锤3 这个游戏的3D引擎代码里,作者是约翰-卡马克(John Carmack),江湖人称卡神。

 注意看代码

这个魔法数 0x5f3759df 。它是从哪来的,又起到了什么作用?

单精度的浮点数结构是这样:
开方的几种写法
那么现在,每个正浮点数 y 可以用尾数和指数的形式写成 
开方的几种写法
,其中 m 是尾数部分,取值范围是 
开方的几种写法
;e 是指数部分,一个整数。每个浮点数所对应的「整数形式」则可以用
开方的几种写法
表示,其中 L 是指数部分需要的位移次数(用 2 的幂表示),E 和 M 是指数部分和小数部分的整数版本。两者之间的关系是
开方的几种写法
对单精度浮点而言,
开方的几种写法
。 考虑对数 
开方的几种写法
,由于
开方的几种写法
开方的几种写法
,取近似
开方的几种写法
,可以算出整体「偏差」最小的
开方的几种写法
,此时两者基本相当。因此我们可以说 
开方的几种写法
……………… (1) 那么,对于 y 的整数形式 Y 而言,展开并带代入 (1) 有:
开方的几种写法
开方的几种写法
………………(2) 那么对于 
开方的几种写法
来说,
开方的几种写法
,代入 (2) 得:
开方的几种写法
解得
开方的几种写法

这个就是代码

的秘密所在。

程序员多学点数学,总是会有用的,与君共勉

附录:java版算法实现

引用文献: