您好,欢迎来到爱问旅游网。
搜索
您的当前位置:首页如何计算整数平方根

如何计算整数平方根

来源:爱问旅游网

算法1.猜试法

利用等差级数公式:        

              

unsigned linear_search(unsigned long x)
{
    unsigned long sum_n = 1;
    unsigned n = 1;

    if(x <= 1)
    {
        return x;
    }

    while(sum_n <= x)
    {
        n++;
        sum_n += (n<<1) - 1;
    }

    return (n-1);

}

 这种方法无异于穷举法,其唯一的优点是:每次的迭代用到了前面迭代的结果,所以会有一些效率的增益。对于该算法的改进就是不穷举,改用我们熟悉的二分查找法来做。

#include<iostream>
#include<string>
using namespace std;

int squareRoot(int n)
{
	int low = 1;
	int high = n;
	while(low<=high)
	{
		int mid = (low+high)/2;
		if(mid*mid == n)
			return mid;
		else if(mid*mid < n)
		{
			low = mid+1;
		}else{
			high = mid;
		}
	}
	return -1;
}
int main()
{	cout<<squareRoot(121)<<endl;
	getchar();
	return 0;
}

算法2 Newton 法

把这个问题转换为方程求根问题,即:

 而方程求根的问题可以用Newton 法来解决。现在的问题有一点不同,即所求的根必须是整数。通过证明,我们可以发现,Newton迭代公式是适用于整数情况的,于是有:

                  

另外,初值的选择也是很重要的一环,这里我们选择大于等于

OK,下面给出程序:

unsigned newton_method(unsigned long x)
{
    unsigned long x1 = x - 1;
    unsigned s = 1;
    unsigned g0,g1;

    /* 初值设定 */
    if (x1 > 65535) {s += 8; x1 >>= 16;}
    if (x1 > 255)   {s += 4; x1 >>= 8;}
    if (x1 > 15)    {s += 2; x1 >>= 4;}
    if (x1 > 3)     {s += 1; x1 >>= 2;}

    /*迭代*/
    g0 = 1 << s;
    g1 = (g0 + (x >> s)) >> 1;
    while(g1 < g0)
    {
       g0 = g1;
       g1 = (g0 + x/g0) >> 1;
    }
    return g0;
}

算法3 逐比特确认法

   逐比特确认法认为一个32位整数求根,结果应该是一个16位整数。求这个16位整数,其实质是确认每位的比特是0还是1.我们把这个根分为两个相加的部分,一部分是已确认的值,另一部分是未确认的值。从高位到低位,每次迭代确认一位。初始时,已确认部分为0。则问题的初始形式为:

                    

unsigned bitwise_verification(unsigned long x)
{

   unsigned long temp = 0;
   unsigned v_bit = 15;
   unsigned n = 0;
   unsigned b = 0x8000;

   if (x <= 1)
       return x;

   do{
       temp = ((n << 1) + b) << (v_bit--);
       if (x >= temp)
       {
           n += b;
           x -= temp;
       }
   }while (b >>= 1);
   
   return n; 
}

性能比较

  在0~1000000范围内对四种算法进行了遍历性的测试,得到测试结果:
      

            

  需要注意的是,虽然平均性能有如此的关系。并不代表每个数或每组数都有这样的关系。实际上,我们每组产生1000个随机数,并对每组的算法性能进行了测试,各个算法都有获得优胜的时候。至于具体是什么场合用什么算法,需要分析和经验的支撑。目前,我所能归纳出的概要指导准则为:

(1)在大多数情况下,牛顿迭代都能获得不错的性能,

(2)逐比特确认法更适合运算数比较大的场合。

测试环境说明:操作系统: windows xp sp3

CPU   : Pentium4 3.0GHZ

内    存: 2.40GHz 0.99GB

编译环境: VC++6.0企业版

参考文献

1.     hacker’s delight 之 初等函数

2.     完全平方数的判定及整数平方根的快速求解 

3.     James Ulery  Computing Integer Square Roots

期间曾因为算法细节问题,向James Ulery求教并得到其热情回复,向其表示感谢。

4.     计算正整数平方根的整数部分(J2ME)

 



因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- awee.cn 版权所有 湘ICP备2023022495号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务