我编写了一个计算sqrt(X)估计值的程序:
对下面代码的解释
我试图找到最近的数字(S)到(x),它可以表示为S=sqrt*sqrt,一直循环到fabs(_sqrt - sqrt) >= 1e-8不正确为止,这意味着sqrt和_sqrt非常接近。
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
double val, min, max;
double sqrt;
double S, _sqrt;
int cnt = 0;
// enter an argument,
if (argc < 2) {
printf ("Usage: sqrt < number >\n");
return 1;
}
val = fabs (atof (argv[1]));
min = 0;//minimum
max = sqrt = val;//maximum
_sqrt = 1;
//1e-8 = 10^(-8) = 0.00000001
while (fabs(_sqrt - sqrt) >= 1e-8) {
_sqrt = sqrt;//keep the old sqrt
sqrt = (max + min) / 2;
S = sqrt * sqrt;
printf("test n(%d)\tsqrt(%lf) = %.6lf\n",++cnt,val, sqrt);
if (S>val){
max = sqrt;//setting max to the current sqrt
} else{
min = sqrt;//setting min to the current sqrt
}//end else
}//end while
puts("");
puts("\t====================================================");
printf ("\tfinal value.\tsqrt(%lf) = %.6lf\n", val, sqrt);
puts("\t====================================================");
return 0;
}//end main()输出
[ar.lnx@host square-root] $ ./sqrt 2
test n(1) sqrt(2.000000) = 1.000000
test n(2) sqrt(2.000000) = 1.500000
test n(3) sqrt(2.000000) = 1.250000
test n(4) sqrt(2.000000) = 1.375000
test n(5) sqrt(2.000000) = 1.437500
test n(6) sqrt(2.000000) = 1.406250
test n(7) sqrt(2.000000) = 1.421875
test n(8) sqrt(2.000000) = 1.414062
test n(9) sqrt(2.000000) = 1.417969
test n(10) sqrt(2.000000) = 1.416016
test n(11) sqrt(2.000000) = 1.415039
test n(12) sqrt(2.000000) = 1.414551
test n(13) sqrt(2.000000) = 1.414307
test n(14) sqrt(2.000000) = 1.414185
test n(15) sqrt(2.000000) = 1.414246
test n(16) sqrt(2.000000) = 1.414215
test n(17) sqrt(2.000000) = 1.414200
test n(18) sqrt(2.000000) = 1.414207
test n(19) sqrt(2.000000) = 1.414211
test n(20) sqrt(2.000000) = 1.414213
test n(21) sqrt(2.000000) = 1.414214
test n(22) sqrt(2.000000) = 1.414214
test n(23) sqrt(2.000000) = 1.414213
test n(24) sqrt(2.000000) = 1.414214
test n(25) sqrt(2.000000) = 1.414214
test n(26) sqrt(2.000000) = 1.414214
test n(27) sqrt(2.000000) = 1.414214
test n(28) sqrt(2.000000) = 1.414214
====================================================
final value. sqrt(2.000000) = 1.414214
====================================================但是它只适用于每一个x>=1,如果我想计算0.5或0.254或0.1的平方.这不管用!
[ar.lnx@host square-root] $ ./sqrt1 0.5
test n(1) sqrt(0.500000) = 0.250000
test n(2) sqrt(0.500000) = 0.375000
test n(3) sqrt(0.500000) = 0.437500
test n(4) sqrt(0.500000) = 0.468750
test n(5) sqrt(0.500000) = 0.484375
test n(6) sqrt(0.500000) = 0.492188
test n(7) sqrt(0.500000) = 0.496094
test n(8) sqrt(0.500000) = 0.498047
test n(9) sqrt(0.500000) = 0.499023
test n(10) sqrt(0.500000) = 0.499512
test n(11) sqrt(0.500000) = 0.499756
test n(12) sqrt(0.500000) = 0.499878
test n(13) sqrt(0.500000) = 0.499939
test n(14) sqrt(0.500000) = 0.499969
test n(15) sqrt(0.500000) = 0.499985
test n(16) sqrt(0.500000) = 0.499992
test n(17) sqrt(0.500000) = 0.499996
test n(18) sqrt(0.500000) = 0.499998
test n(19) sqrt(0.500000) = 0.499999
test n(20) sqrt(0.500000) = 0.500000
test n(21) sqrt(0.500000) = 0.500000
test n(22) sqrt(0.500000) = 0.500000
test n(23) sqrt(0.500000) = 0.500000
test n(24) sqrt(0.500000) = 0.500000
test n(25) sqrt(0.500000) = 0.500000
test n(26) sqrt(0.500000) = 0.500000
====================================================
final value. sqrt(0.500000) = 0.500000
====================================================有人能帮我弄清楚问题是什么以及如何解决吗?
发布于 2016-01-29 17:08:07
原因是您的转换逻辑只有在val > 1时才能工作。
注意测试sqrt(.5)的方式,因为val == 0.5获得了S = val * val,即0.25。这将min重置为0.25,因为sqrt = (max + min) / 2;和初始max是val (0.5),您永远无法通过0.5。
您必须确定,由于您的初始val小于1,所以您希望初始max为1,因此您的平均值为val < sqrt < 1。
如果您这样做,那么您应该收敛到正确的值。
此时我无法访问C编译器。但是,通过初步检验,第一个平均值是1.5/2 == .75,它重置了最大值。新的平均值是1.25/2 == .625,它重置最小值,然后继续,直到收敛到正确的值为止。
FYI您也可以使用while循环的内容作为一个不同的函数来教自己递归。也就是说,如果S> lim {调用新的估计函数}一旦它通过递归,它将传递最后的估计值回初始调用函数,而不是循环遍历时间。
发布于 2016-01-29 17:03:34
问题在于您的max值,它必须大于或等于预期的结果。如果您的输入小于1.0,则结果大于输入,小于1.0。您对max的价值至少必须是1.0。像这样调整你的代码。
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
double val, min, max;
double sqrt;
double S, _sqrt;
int cnt = 0;
// enter an argument,
if (argc < 2) {
printf ("Usage: sqrt < number >\n");
return 1;
}
val = fabs (atof (argv[1]));
if ( val < 1.0 )
{
min = val;
max = sqrt = 1.0; // if val < 1.0 result is greater than val but less than 1.0
}
else
{
min = 0; //minimum
max = sqrt = val; //maximum
}
do
{
_sqrt = sqrt;//keep the old sqrt
sqrt = (max + min) / 2;
S = sqrt * sqrt;
printf("test n(%d)\tsqrt(%lf) = %.6lf\n",++cnt,val, sqrt);
if (S>val){
max = sqrt;//setting max to the current sqrt
} else{
min = sqrt;//setting min to the current sqrt
}//end else
}
while ( fabs(_sqrt - sqrt) >= 1e-8); //1e-8 = 10^(-8) = 0.00000001
puts("");
puts("\t====================================================");
printf ("\tfinal value.\tsqrt(%lf) = %.6lf\n", val, sqrt);
puts("\t====================================================");
return 0;
}https://stackoverflow.com/questions/35089813
复制相似问题