我的平方根函数对某些数字不能给出准确的结果

My Square Root Function does not give accurate results for some numbers

本文关键字:结果 不能 数字 函数 平方根 我的      更新时间:2023-10-16

我需要为课程作业编写一个平方数字的函数。它可以计算像16和25这样的数字的平方根,但不能精确计算9的平方根。

下面是代码
 double mysqrt (double x)
{
   double low, high, mid;

if语句决定创建一个范围来确定平方根。

   if (x >= 0) {
      low = 0;
      high = x;
   }
   else {
     low = x;
     high = 1;
   }

这个语句计算中间值

   mid = (high + low)/2.0;

while循环用于确定平方根。

   while (abs(mid*mid - x) > 0.0001)
   {
      if (mid * mid > x)
          high = mid;
      else
          low = mid;
      mid = (high/2.0) + (low/2.0);
   }
   return mid;
 }

通常我不只是为他们做作业,但我想挑战这样一种观点,即收敛性应该总是通过将误差与固定的epsilon值进行比较来检测。

请记住,double数据类型只能表示有限范围内的值,因此比较两个结果之间的等价性可用于检测收敛性,其中任意精度的比较可能导致无限迭代

另外,一组可能的浮点值是分布的,因此一个值与下一个值之间的差对于小值比大值更小,所以如果你使用epsilon,通常不适合将其固定在某个任意的"小"值上。

下面的代码执行相同的愚蠢的二进制搜索,但是退出条件测试是否重新访问前一次迭代的结果,这意味着进一步的迭代将永远重复覆盖相同的搜索状态,并且错误接近于可能的最小值。

通过这种方式,epsilon自动由double数据类型本身以及输入来确定。如果您用某种任意精度类替换double,那么您确实需要提供一个epsilon,否则非理性根可能会循环直到某种失败,例如内存不足的情况。

#include <iostream>
#include <iomanip>
double mysqrt(double x) {
    double low, high;
    if(x < 1) {
        if(x <= 0) return 0;
        low = x;
        high = 1;
    } else {
        low = 1;
        high = x;
    }
    for(;;) {
        const double mid = (low + high) / 2;
        if(high == mid || low == mid) return mid;
        if(mid * mid > x) {
            high = mid;
        } else {
            low = mid;
        }
    }
}
int main() {
    std::cout <<  std::setprecision(14) << mysqrt(3) << 'n';
}