class Program

{

    static float SqrtByTwoDivide(float number)

    {

        if (number < 0f)

        {

            throw new ArithmeticException();

        }

        

        if (number == 0 || Math.Abs(number - 1f) < float.Epsilon)

        {

            return number;

        }

        

        float left,right;

        if (number > 1f)

        {

            // 如果大于1,那么1 ~ number之间进行二分

            left = 1;

            right = number;

        }

        else

        {

            // 如果小于1,在number ~ 1 之间进行二分

            left = number;

            right = 1;

        }

        float result = (left + right) / 2;

        while (Math.Abs(result * result - number) > float.Epsilon)

        {

            // 这里是因为精度考虑,有可能左值和右边已经非常接近,无法产生新的中间值

            if (Math.Abs(result - left) < float.Epsilon || Math.Abs(result - right) < float.Epsilon)

            {

                return result;

            }

            if (result * result > number)

            {

                right = result;

                result = (left + right) / 2;

            }

            else if (result * result < number)

            {

                left = result;

                result = (left + right) / 2;

            }

            else

            {

                return result;

            }

        }

        return result;

    }



    static void Main(string[] args)

    {

        Console.WriteLine(SqrtByTwoDivide(0.000001f));

        Console.WriteLine(SqrtByTwoDivide(0.5f));

        Console.WriteLine(SqrtByTwoDivide(1.5f));

        Console.WriteLine(SqrtByTwoDivide(10f));

        Console.WriteLine(SqrtByTwoDivide(12345678f));

    }

}

输出结果:


0.0009999999

0.7071068

1.2247448

3.1622777

3513.6416

需要注意的问题:

  1. 精度问题,计算机没有办法准确表示一个浮点值,所以判断的时候,需要使用Abs和Epsilon来判断相等;

  2. 当left和right足够接近的时候,(left + right) * 0.5f 无法产生一个新的值,这个时候也要及时结束。