开方怎么算才能精确到小数点后N位?

时间:2021-03-12 18:31:38
开方怎么算才能精确到小数点后N位?
比如说,sqr2要精确到小数点后100位,用C语言怎么编写程序啊?

10 个解决方案

#1


首先开方运算必须采用迭代法,至于精确到100位,必须编写专门的程序,c语言提供的基本数据类型无法直接给出.

#2


用迭代法求a的平方根
Xn+1=1/2*(Xn+a/Xn)
取Xo=a/2

#3


网上有例程,下一个看看。你可以用一个整型数组存储结果。

#4


用二分法可以编写一个速度不是很快的程序
其中用数组保存计算结果
编写要比用迭代公式Xn+1=1/2*(Xn+a/Xn)简单的多
因为不用除法
速度慢些
但计算100位足够了

#5


用级数展开

#6


用泰勒公式展开为级数即可。

#7


迭代法速度最快

#8


用快速截弦法比较好.只有-和*的运算.

以下是转自colacoca兄的话:

牛顿法突出优点是收敛的速度快。但它有个明显的缺点:需要计算导数f'(x),如果函数f(x)比较复杂,使用牛顿法是不方便的。
为了避开导数计算,就用差商:
(f(Xk)-f(X0))/(Xk-X0)
......
用以替换牛顿公式中得导数f'(Xk)
最后得

Xk+1=Xk-f(Xk)*(Xk-X0)/(f(Xk)-f(X0))
求得的Xk+1其实就是弦线与X轴的交点,所以上面的算法称弦截法

然后又是一阵推导.....
......
最后,为了加快收敛速度,改用差商
(f(Xk)-f(Xk-1))/(Xk-Xk-1)
得出快速弦截法的公式:
Xk+1=Xk-f(Xk)*(Xk-Xk-1)/(f(Xk)-f(Xk-1))

注:上面的Xk,Xk+1,Xk-1中的k,k-1,k+1都是X的下标,不是变量Xk减去1的意思

所以才有我的
x1=x0;
x0=x; 
x=x0-(x0-x1)*(x0^2-A)/((x0^2-A)-(x1^2-A));
这3个式子

#9


我用Borland C++ 3.1编写了一个算法,main调用sqrt计算2的算术平方根。更通用的算法只要更改一下main即可。这里的算法已经把原理解释的足够清楚。
本程序中,常数W表示数据的总位数,D标是小数部分位数。
#include <stdio.h>
#include <string.h>

const W=101;
const D=100;

int pos(int power){
  return power+D;
}

int power(int pos){
  return pos-D;
}

void fill(int d[W],int t){
  for (int i=0;i<W;i++) d[i]=t;
}


void copy(int x[W],int y[W]){
  for (int i=0;i<W;i++) y[i]=x[i];
}

void assign(int x[W],char* n, char* d){
  fill(x,0);
  char *p;
  p=n;
  int L=strlen(n);
  int i;
  for (i=L-1;i>=0;i--,p++) x[pos(i)]=*p-'0';
  L=strlen(d);
  p=d;
  for (i=-1;i>=-L;i--,p++) x[pos(i)]=*p-'0';
}

int equal(int x[W],int y[W]){
  for (int i=W-1;i>0;i--)
    if (x[i]!=y[i]) return 0;
  return 1;
}

void mid(int x[W],int y[W],int z[W]){
  z[0]=x[0]+y[0];
  for (int i=1;i<W;i++){
    z[i]=x[i]+y[i]+z[i-1]/10;
    z[i-1]=z[i-1]%10;
  }
  for (i=W-1;i>0;i--) {
    z[i-1]+=(z[i]*10)%20;
    z[i]/=2;
  }
  z[0]/=2;
}

void sqr(int x[W], int y[W]){
  fill(y,0);
  for (int i=0;i<W;i++){
    for (int j=0;j<W;j++){
      int t=pos(power(i)+power(j));
      if ((t>=0)&&(t<W)) y[t]+=x[i]*x[j];
    }
  }
  for (i=0;i<W-1;i++){
    y[i+1]+=y[i]/10;
    y[i]=y[i]%10;
  }
  y[W-1]=y[W-1]%10;
}

int compare(int x[W],int y[W]){
  for (int i=W-1;i>=0;i--){
    if (x[i]<y[i]) return -1;
    if (x[i]>y[i]) return 1;
  }
  return 0;
}

void print(int x[W]){
   int i;
   for (i=W-1;i>=0;i--){
     printf("%c",'0'+x[i]);
     if (i==D) printf(".");
   }
   printf("\n");
}

void sqrt(int x[W],int y[W]){
   int a[W],b[W],c[W];
   fill(a,0);
   copy(x,b);
   b[pos(0)]++;
   while (!equal(a,b)) {
      mid(a,b,c);
      sqr(c,y);
      if (compare(y,x)<0) copy(c,a);
      else copy(c,b);
   }
   copy(c,y);
   return;
}

void main(){
   int x[W],y[W];
   assign(x,"2","0");
   sqrt(x,y);
   print(y);
}































#10


up

#1


首先开方运算必须采用迭代法,至于精确到100位,必须编写专门的程序,c语言提供的基本数据类型无法直接给出.

#2


用迭代法求a的平方根
Xn+1=1/2*(Xn+a/Xn)
取Xo=a/2

#3


网上有例程,下一个看看。你可以用一个整型数组存储结果。

#4


用二分法可以编写一个速度不是很快的程序
其中用数组保存计算结果
编写要比用迭代公式Xn+1=1/2*(Xn+a/Xn)简单的多
因为不用除法
速度慢些
但计算100位足够了

#5


用级数展开

#6


用泰勒公式展开为级数即可。

#7


迭代法速度最快

#8


用快速截弦法比较好.只有-和*的运算.

以下是转自colacoca兄的话:

牛顿法突出优点是收敛的速度快。但它有个明显的缺点:需要计算导数f'(x),如果函数f(x)比较复杂,使用牛顿法是不方便的。
为了避开导数计算,就用差商:
(f(Xk)-f(X0))/(Xk-X0)
......
用以替换牛顿公式中得导数f'(Xk)
最后得

Xk+1=Xk-f(Xk)*(Xk-X0)/(f(Xk)-f(X0))
求得的Xk+1其实就是弦线与X轴的交点,所以上面的算法称弦截法

然后又是一阵推导.....
......
最后,为了加快收敛速度,改用差商
(f(Xk)-f(Xk-1))/(Xk-Xk-1)
得出快速弦截法的公式:
Xk+1=Xk-f(Xk)*(Xk-Xk-1)/(f(Xk)-f(Xk-1))

注:上面的Xk,Xk+1,Xk-1中的k,k-1,k+1都是X的下标,不是变量Xk减去1的意思

所以才有我的
x1=x0;
x0=x; 
x=x0-(x0-x1)*(x0^2-A)/((x0^2-A)-(x1^2-A));
这3个式子

#9


我用Borland C++ 3.1编写了一个算法,main调用sqrt计算2的算术平方根。更通用的算法只要更改一下main即可。这里的算法已经把原理解释的足够清楚。
本程序中,常数W表示数据的总位数,D标是小数部分位数。
#include <stdio.h>
#include <string.h>

const W=101;
const D=100;

int pos(int power){
  return power+D;
}

int power(int pos){
  return pos-D;
}

void fill(int d[W],int t){
  for (int i=0;i<W;i++) d[i]=t;
}


void copy(int x[W],int y[W]){
  for (int i=0;i<W;i++) y[i]=x[i];
}

void assign(int x[W],char* n, char* d){
  fill(x,0);
  char *p;
  p=n;
  int L=strlen(n);
  int i;
  for (i=L-1;i>=0;i--,p++) x[pos(i)]=*p-'0';
  L=strlen(d);
  p=d;
  for (i=-1;i>=-L;i--,p++) x[pos(i)]=*p-'0';
}

int equal(int x[W],int y[W]){
  for (int i=W-1;i>0;i--)
    if (x[i]!=y[i]) return 0;
  return 1;
}

void mid(int x[W],int y[W],int z[W]){
  z[0]=x[0]+y[0];
  for (int i=1;i<W;i++){
    z[i]=x[i]+y[i]+z[i-1]/10;
    z[i-1]=z[i-1]%10;
  }
  for (i=W-1;i>0;i--) {
    z[i-1]+=(z[i]*10)%20;
    z[i]/=2;
  }
  z[0]/=2;
}

void sqr(int x[W], int y[W]){
  fill(y,0);
  for (int i=0;i<W;i++){
    for (int j=0;j<W;j++){
      int t=pos(power(i)+power(j));
      if ((t>=0)&&(t<W)) y[t]+=x[i]*x[j];
    }
  }
  for (i=0;i<W-1;i++){
    y[i+1]+=y[i]/10;
    y[i]=y[i]%10;
  }
  y[W-1]=y[W-1]%10;
}

int compare(int x[W],int y[W]){
  for (int i=W-1;i>=0;i--){
    if (x[i]<y[i]) return -1;
    if (x[i]>y[i]) return 1;
  }
  return 0;
}

void print(int x[W]){
   int i;
   for (i=W-1;i>=0;i--){
     printf("%c",'0'+x[i]);
     if (i==D) printf(".");
   }
   printf("\n");
}

void sqrt(int x[W],int y[W]){
   int a[W],b[W],c[W];
   fill(a,0);
   copy(x,b);
   b[pos(0)]++;
   while (!equal(a,b)) {
      mid(a,b,c);
      sqr(c,y);
      if (compare(y,x)<0) copy(c,a);
      else copy(c,b);
   }
   copy(c,y);
   return;
}

void main(){
   int x[W],y[W];
   assign(x,"2","0");
   sqrt(x,y);
   print(y);
}































#10


up