《雷神之锤 Ⅲ》平方根倒数速算法魔术数字的另一种求法(2)

上图代码是出自雷神之锤3计算一个正实数的算术平方根的倒数的算法,一般我们去计算一个数的平方根采用最好的方法是牛顿迭代法

不会牛顿迭代法,可以去看下这位大哥的帖子

www.cnblogs.com/houkai/p/3332520.html

比如我们要求 x 的平方根倒数,就可以构造一个关于y的函数      f(y)=\frac{\1 }{y^2}-x

把这个函数代入牛顿迭代公式里面就可以求出迭代形式

                                

这就是第 5、6、11 行代码的由来,我们知道通过上图公式一直迭代计算下去,这个函数在f(y)=0处有收敛,此时 y  的值即为所求

 牛顿迭代法计算平方根的倒数,如果迭代次数过多,会影响计算机性能,那么能不能在这个收敛值的附近先找出一个预解值出来,从而快速计算到收敛值,减少迭代次数减少计算量?这个思想从而就引出了这个神迹代码,也就是整个代码的核心思想,这个预解值就是用第8、9、10这三行代码计算出来

 第8行代码:先将要求的浮点数转换成浮点数二进制表示法下的整数,不会浮点数二进制表示法可以去看看这位大哥的帖子 

blog.csdn.net/wangshuaiwsws95/article/details/105874684

第9行代码:将转换成整数的值除以2,也就是 i>>1 往右移动一位,再用0x5f3759df这个常数去减它

第10行代码:将第9行代码求出来的整数值强制转换成浮点数,这样就得到了一个预解值,牛顿迭代一次精度可到小数点后三位。

非常神奇!

大家对这个代码的理解基本上来自维基百科上的解释!可以去看这位大哥的帖子

blog.csdn.net/weixin_43899202/article/details/120540104

本人从另外一个角度来考虑了这个问题:

按照浮点数二进制表示法,一个任意大于0(小于等于0在计算机中不能开根号)能存储在32位的浮点数转换成二进制整数时,至少是   2^{24}-1这个数,第9行代码明显是一个一次函数,浮点数曲线函数转换成二进制整数时,把这条曲线放大了很多倍,当成一条直线去计算,当然这种放大并不是线性的放大。

一条曲线无限放大就是一条模糊直线,可以通过最小二乘法去计算这条模糊直线的解析式,早就有的数学模型,也就是古人说的天圆地方,地球是平的

y=x^{-0.5} 这个幂函数在浮点数二进制表示成整数后,把这个曲线函数放大后转换成了一次函数y=-0.5x+0x5f3759df,计算完成再缩回去,把32位二进制整数再变回浮点数。

浮点数转二进制整数、二进制整数转浮点数  :这种转换关系应该就是函数与反函数的转换关系。

                                                             最小二乘法公式:

                                                      

                                       有了上面这个思路 于是我在y=x^{-0.5}找了一串数

总共45组浮点数转换成二进制整数表示,再代入最小二乘法公式中求得直线方程为

y=-0.500171439x+1597492523.68

不可能再将整数转成浮点数再去计算,所以舍去一些精度,斜率值定在0.5,常数值1597492524比0X5f3759df精度要差一些

其实没有绝对精度的常数值,斜率不变,只动常数值,直线会左移或者右移,只要不太偏离这条模糊直线,在某些数值区域总有精度你比我高,或者我比你高,看谁高的区域多些,就认为哪个常数值比较好!

当我去掉  1^{-0.5}=1 这组数时,斜率值是-0.500001819,此时常数值是1597292554.53

当我再去掉 2^{-0.5}=0.7071067811865475 这组数时,斜率值是-0.49999941,此时常数值是1597289491.83

因此我认为最佳值应该在 1597289491.83-1597292554.53之间,

依据斜率值与常数值的线性关系计算,最佳常数值应该是1597289588转换成16进制0x5F34B474

穷举了下0x5f3759df和0x5f34b474 在1-1000000之间,看谁的精度次数高,代码如下

 明显0x5f34b474精度要高出一倍多

至于0x5f3759df 这个神秘常数的由来,我也搞不清楚!

大家可以依据此方法去计算64位浮点下计算平方根倒数的常数或者开平方根、立方根等一些曲线函数的计算常数!

计算要用EXCEL去算,计算数值太大,C语言64位整数装不下!

由于芯片技术的发展,SIMD等矢量指令集的出现,此计算方法已成为时代的产物,但是前辈大佬的脑洞大开,为我们展示了数学之美!!!!!!!,向发明此算法的大佬致敬!!!!!!!!

     

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南风.吐月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值