我有一个代码,可以通过以下方式计算数字的平方根:
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)
的近似值。
你用n
和i
调用函数,现在,只要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);