(.NET)利用二分查找实现任意整数的开方运算

群里面有人传了一道面试题,大致意思就是求任意整数的开方运算。

  public static string Squre(int input)
        {
            if (input == 0)
            {
                return "0";
            }
            if (input < 0)
            {
                input = input * (-1);
            }
            double min = 0;
            int i = 0;
            while (true)
            {
                i++;
                if (i * i == input)
                {
                    return i.ToString();
                }
                if (i * i >= input)
                {
                    min = i - 1;
                    int count = 0;
            //我是关键 //这里可以用for循环来实现,但是for的效率。。。。运行个几万十万次都很正常
Console.WriteLine("=========================手写========================"); Console.WriteLine("手写次数:" + count); return input < 0 ? s : s + "i"; } } }

while(true)中的意思是我求出所有的正整数的平方与输入的数字进行比较,

比如,我们求5的开方,那么5的开方肯定在2*2与3*3之间,那么结果肯定就是2-3之间的

某个数,使用for循环的话,需要从2加个精度的小数一直加到x*x>input为止,那么,

在某些情况下for循环执行的次数肯定是我们不希望的,所以下面放出递归代码:

关键部分调用:

string s = Find(min, input, 1, ref count).ToString();
public static double Find(double min, int input, double x, ref int count)
        {
            count++;
            double m = (min + x / 2) * (min + x / 2);
            double result;
            if (m > input)
            {
                if (m - input < 0.000000000001)
                {
                    result = min + x / 2;
                    return result;
                }
                else
                {
                    return Find(min, input, x / 2, ref count);
                }
            }
            else if (m < input)
            {
                if (input - m < 0.000000000001)
                {
                    result = min + x / 2;
                    return result;
                }
                else
                {
                    return Find(min + x / 2, input, x / 2, ref count);
                }
            }
            else
            {
                result = min + x / 2;
                return result;
            }
        }

使用一个递归来,运行次数只有几十次就可以得出结果,运行效率极大提高,来测试下:

 static void Main(string[] args)
        {
            Thread.Sleep(1000);//怕程序启动的时候对下面的运行有影响
            Stopwatch sp = new Stopwatch();
            Console.WriteLine("=========================自带========================");
            sp.Start();
            Console.WriteLine("math:" + Math.Sqrt(9999999));
            sp.Stop();
            Console.WriteLine("用时:" + sp.ElapsedMilliseconds);
            sp.Restart();
            Console.WriteLine("手写:" + Squre(9999999));
            sp.Stop();
            Console.WriteLine("用时:" + sp.ElapsedMilliseconds);
            Console.ReadKey();
        }

结果如下:

=========================自带========================
math:3162.27750205449
用时:0
=========================手写========================
手写次数:39
手写:3162.27750205449
用时:1

我自己测试了很多次,有些时候运行时间比math多,有些时候比math少;

递归的主要思路:

input肯定是位于min和max之间某个数的平方,那么取min和max的中间数的

平方与input比较,如果大于input那么,在(min+(max-min)/2)到max之间就存在一个

数的平方等于input,接下来继续判断,如果第二次调用find,还是大于input,那么,

在((min+(max-min)/2)+(max-(min+(max-min)/2))/2)到max之间可以找到这个数,依次,

一直找到我们代码中所写的条件为止就ok了。

 

posted @ 2017-12-08 16:38  ll老绵羊  阅读(548)  评论(0)    收藏  举报