用于计算平方根的递归算法



我有一个代码,可以通过以下方式计算数字的平方根:

void f1(int,int);
int main(){
    int i=1;
    int n;
    scanf("%d",&n);
    f1(n,i);
    getch();
    return 0;
}
void f1(int n,int i){
    if((n*10000)-(i*i)<=0)
        printf("%f",(double)i/100);
    else
        f1(n,i+1);
}

我不知道为什么要使用n*10000 - i*i.有人可以解释一下这个代码吗?

让我们考虑n=100的例子。对于第一堆递归,我们有i=1,2,3,... . 因此,对于这些调用,我们有 n*10000 - i*i >= 0 .然后在某个时候,我们已经i=999并观察n*10000 - 999*999 >= 0 .下一个递归步骤已经i=1000,我们看到n*10000 - 1000*1000 <= 0,所以我们打印(double)i / 100,然后就是10。如您所见,结果只是 n=100 的 sqare 根 .

一般来说,满足n*10000 - i*i <= 0的最小数i/100"非常接近"n的平方根,原因如下:

sqrt(n*10000) = sqrt(n)*sqrt(10000) = sqrt(n)*100

我们有:

n*10000 - i*i <= 0            | +i*i
      n*10000 <= i*i          | sqrt both sides
  sqrt(n)*100 <= i            | /100
      sqrt(n) <= i/100

因此,我们正在寻找大于或等于 sqrt(n) 的最小数i/100,并将该数字用作 sqrt(n) 的近似值。

你用ni调用函数,现在,只要i*i小于n * 10000,您就会增加i

如果您的 I*i 大于 N * 10000,则打印 I/100

例如:你用f1(1,1)调用函数:

 1*10000 >= 1*1 --> f1(1,2);
 1*10000 >= 2*2 --> f1(1,3);
 1*10000 >= 3*3 --> f1(1,4);
 ....
 1*10000 >= 99*99 ->f1(1,100);
 1*10000 <= 100*100 --> printf("%f",i/100.0); which gives: 1

编辑:另一个例子,你寻找8的sqare根:f1(8,1);

 8*10000 >= 1*1 --> f1(8,2);
 8*10000 >= 2*2 --> f1(8,3);
 1*10000 >= 3*3 --> f1(8,4);
 ....
 8*10000 >= 282*282 ->f1(8,283);
 8*10000 <= 283*283 --> printf("%f",i/100.0); which gives: 2.83
 and 2.83 * 2.83 = 8.0089

编辑:你可能会问为什么n*10000,这是因为计算误差变小,例如:如果你在8个例子的sqrt中使用n * 100和i/10,你会得到

8*100 <= 29*29 --> 2.9
2.9 * 2.9 = 8.41 which is not good as 2.83 in the other example

这只是为了增加一些精度。

void f1(int n,int i){
    printf("value of i is=%d n",i);
    if(n-i*i<=0)
        printf("%f",i);
    else
        f1(n,i+1);
}

此代码仅适用于完美平方数。

void f1(int n,int i){
    printf("value of i is=%d n",i);
    if((n*100)-(i*i)<=0)
        printf("%f",(double)i/10);
    else
        f1(n,i+1);
}

此代码适用于所有数字,但只会给出浮点后一位数字的结果。

void f1(int n,int i){
    printf("value of i is=%d n",i);
    if((n*10000)-(i*i)<=0)
        printf("%f",(double)i/100);
    else
        f1(n,i+1);
}

这是您的代码,它在浮点后提供 2 位点精度。因此,根据您的要求,(n*10000)-(i*i)是必需的。如果你想只找到完美的,你也可以使用第一个代码。

考虑这个函数:

void f1(int n,int i){
    if((n)-(i*i)<=0)
        printf("%f",i);
    else
        f1(n,i+1);
}

这个函数会递归循环 i,直到 i^2>=n,它基本上与没有递归的情况下这样做相同:

void f1(int n,int i){
    int i = 1;
    while (i*i < n)
        ++i;
    printf("%f",i);
}

现在 10000 的诀窍只是添加一些由大整数模拟的精度(请注意,它可能会像这样更快地溢出 int) - 你计算 sqrt(100*100*n),即 100*sqrt(n),所以你把结果除以 100。这使您可以获得 2 位数的精度。

因为它会使结果四舍五入到两位小数。

例如 n=10 结果是 3.17。

如果你想得到四舍五入到3位小数的结果,你可以写:

if((

n*1000000)-(i*i)<=0) printf("%f",(double)i/1000);

最新更新