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
需要注意的问题:
-
精度问题,计算机没有办法准确表示一个浮点值,所以判断的时候,需要使用Abs和Epsilon来判断相等;
-
当left和right足够接近的时候,
(left + right) * 0.5f无法产生一个新的值,这个时候也要及时结束。