user-0 提问: 如何实现高精度或无限精度的小数位的乘除法

回复:
user: user-1
content: 补一句，用浮点数做基本数据结构来表示无限精度，代码太复杂了，还是用整数吧，这样精度的刻度划分是平均的，代码写起来比较容易。计算机运算速度应该要快一些吧？

user: user-1
content: 提供一个算法思路，代码自己写。 我们知道浮点数的精度主要取决于它的尾数部分，如果尾数部分是23位，那么实际上就是在浮点数范围内，取实数的2^23个子集，构成计算机所有能表示的数。 对于某无理数a，假如a的值范围在该子集两个数字B,C之间，那么我们在把这两个数B,C之间的实数再次分为2^23份，然后再进行计算比较，得出a的值在C,D之间，如此循环操作下去，想要多少精度就有多少精度。当然，还要考虑计算机工作时间问题，不可能永远计算下去，差不多就行了吧。。。

user: user-2
content: 仅供参考：// 按下列数级计算e的近视值，使e有小数点后1000位有效数字。 // e=1+1/1!+1/2!+1/3!+......1/n! #include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     string s1,s2,s3,s4;     int i;      s4="0";      s3="1";     for (i=0;i<1002;i++) s3+="0";      s1="1";     s2="1";      s4=ADD_INT(s4,DIV_INT(s3,s1));     s4=ADD_INT(s4,DIV_INT(s3,s1));      for (i=2;i<451;i++) {//因为450!是一个1001位数         s2=ADD_INT(s2,string("1"));         s1=MUL_INT(s1,s2);         s4=ADD_INT(s4,DIV_INT(s3,s1));     }      cout<<s4<<endl;      return(0); } //271828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992 //181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924 //476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320 //070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598 //793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311 //730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035 //159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023 //530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770 //4171898610687396965521267154688957035035174

user: user-3
content: 引用 4 楼 lm_whales 的回复:ＩＥＥＥ754浮点数（数学）协处理器 主要不使用来做　+，-,*,/ 而是用硬件实现了各种数学函数，当然也实现了+，-,*,/

user: user-3
content: ＩＥＥＥ754

user: user-3
content: 无限精度小数？ 别用浮点数了， 连分式表示就可以了。 理论上所有实数，都可以用连分式，有效的表示出来。 无理数，可以用有限循环连分式表示。  高精度小数，可以用数组表示， 一部分表示整数，一部分表示小数 ， 还可以一部分表示指数， 可以仿照754　表示方法，不过所有浮点运算，要自己设计算法。  浮点运算的效率，各种数学函数的高效实现。 才是问题所在。

user: user-0
content: 这问题都没人回答么？CSDN都烂成这样了？

user: user-4
content: 引用 2 楼 kkyyff2008 的回复:这问题都没人回答么？CSDN都烂成这样了？ 不好意思，让你久等。你问的问题有点难度。 两个整数相除的参考代码如下：   //copyright by x.&.x  #include <stdio.h> #define N 21  void chufa(int bc,int c) { 	int i,j,mod,w,cn=10,res[N]; 	for(i=0;c-cn>0;i++) 		cn*=10; 	for(w=0,mod=1;w<N&&mod!=0;w++) 	{ 		res[w]=bc/c; 		mod=bc%c; 		bc=mod*cn; 	} 	printf("%d.",res[0]); 	if(i==0) 	{ 		for(i=1;i<w;i++) 				printf("%d",res[i]); 	} 	else if(i==1) 	{ 		for(i=1;i<w;i++) 			printf("%02d",res[i]); 	} 	else if(i==2) 	{ 		for(i=1;i<w;i++) 			printf("%03d",res[i]); 	} 	else if(i==3) 	{ 		for(i=1;i<w;i++) 			printf("%04d",res[i]); 	}	         else 	{ 		printf("待续......"); 	} 	printf("\n"); }  int main() { 	int bc,c; 	printf("请输入被除数和除数:"); 	scanf("%d%d",&bc,&c); 	chufa(bc,c); 	return 1; } 希望对你有帮助。 测试部分如下:

user: user-5
content: 自行实现大数逻辑或者借用别人写好的。无限精度是不可能的，不说算，你想想你写出来根号2的小数表示就需要无限长的时间和无限多的纸。