开平方算法

开平方算法

开平方算法的算法有很多,最简单的莫过于穷举法,例如在精度x下,每次增加一个x,直到逼近被开方数,还有二分法等。
以下谈论两种比较有实际意义的算法。

牛顿迭代法

inline float Newton(float n)
{
	float x1 = n;
	float x2 = n / 2;

	while (fabs(x1 - x2) > 0.000001)//精度
	{
		x1 = x2;
		x2 = (x1 + n / x1) / 2;
	}
	return x1;
}

牛顿法迭代法是二次收敛的,通过它我们可以得到一个近似解,可以自行提高计算精确。其实在实际生活中,只要精度足够用就好了。
结果检验:

	cout << "Newton(2)\t"<<Newton(2)<<endl;
	cout << "sqrt(2)\t"<<sqrt(2);

sqrt(2) 1.414214
Newton(2) 1.414214

可见精度还是相当高了

平方根倒数算法

inline float qrsqrt(float n)
{
	long i;
	float x, y;
	x = n /2;
	y = n;
	i = *(long *)&y;
	i = 0x5f3759df - (i >> 1);
	y = *(float *)&i;
	y = y * (1.5 - (x * y * y));
	return y;
}

其中:
i = *(long *)&y 把浮点类型数强转为一个整形数字的二进制表示
i = 0x5f3759df - (i >> 1) 这一步不需要太明白0x5f3759df是什么,理解为到得到一个近似的整型解就可以了,它并没有提高迭代收敛速度,而是得到了一个优秀的迭代初值点。
y = *(float *)&i 这是 i = *(long *)&y的逆操作,将上一部的到的整型近似解转为
浮点型
y = y * (1.5 - (x * y * y)) 最后执行一次牛顿迭代,提高进度,这一步可以重复多次来提高精度
它的优点在于计算速度快,速度快了必然精度就差了,精度要想提高就必须增加迭代次数,迭代次数增加计算速度就的降低

结果检验:

	cout << "1/qrsqrt(2)\t"<< 1/qrsqrt(2)<<endl;

1/qrsqrt(2) 1.41457
显然精度略低

当增加执行一次牛顿迭代 y = y * (1.5 - (x * y * y)) 后

1/qrsqrt(2) 1.414214
可见牛顿迭代是提高精度的核心

效率比较

#include "stdafx.h"
#include<iostream>
#include<time.h> 
using namespace std;
int main() {
	int start, end;
	int i = 0;
	start = clock();	//计时开始

	cout << Q_rsqrt(4) << endl;
	//在精度相同的情况下测试
	for (long i = 0; i < 100000000; i++) {
		sqrt(i);//end- start:1869ms
		//1/qrsqrt(i);//end- start:4477ms
		//Newton(i);//end- start:88329ms
	}
	end = clock();	//计时结束
	cout<<"\end- start:%dms\n"<<(end - start);
}

不难看出Newton迭代法要低出一个数量级 ,qrsqrt算法得益于它优先找到了一个近似解,减少了不必要的迭代过程,如果Newton迭代法能找到一个优异的初值点的话收敛速度也会和qrsqrt算法起鼓相当。
当然,在原生函数 sqrt 高效的计算速度和超高精度的光芒下,一切都会黯然失色。

_Check_return_ inline float sqrt(_In_ float _Xx) _NOEXCEPT
	{
	return (_CSTD sqrtf(_Xx));
	}

很无奈找不到sqrt的本尊,无法窥探究竟,我想可能是它有着更底层的实现或者是编译器的支持吧。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值