128位乘除法怎么算?
各位大大好,小弟现在写的是嵌入式程序,我的开发软件最大只支持64位数据(long long int),可是现在计算的量已经超过这个值了,哪位大大能教教小弟怎么算128位的啊?我的开发环境数据位是这样的(char 8位、short 16位、long 32位、long long 64位)。小弟的分不多,还望见谅,先谢过了啊!
我要算的公式是这样的:
Z=a*X+(1-a)Y;a=128/(t+128);t是在10 000到30 000 000之间变化的,运算过程中不用浮点数。
[解决办法]
算法参考小学三年级乘除法竖式。(^_^)
仅供参考:
#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() { char ch; string s1,s2,res; while (cin>>s1>>ch>>s2) { switch (ch) { case '+':res=ADD_INT(s1,s2);break; case '-':res=SUB_INT(s1,s2);break; case '*':res=MUL_INT(s1,s2);break; case '/':res=DIV_INT(s1,s2);break; case '%':res=MOD_INT(s1,s2);break; default : break; } cout<<res<<endl; } return(0);}
[解决办法]
呵呵,用数组表示吧!~
[解决办法]
软浮点支持
[解决办法]
假设A、B、C、D都是64位整数,AB、CD组合成128位整数
AB * CD = (A0 + 0B) * (C0 + 0D)
=A0 * C0 + A0 * 0D + 0B * C0 + 0B * 0D
这里的0代表64位0
A0 * C0大于2^64,舍去
0B * 0D就是一个普通的64位之内的乘法,完全保留
A0 * 0D + 0B * C0的低32位全0,实际上你需要做的就是保留A * D和B * C的低32位,再逻辑左移32位
一个128位乘法,可化为3个64位乘法,2个64位逻辑左移和2个64位加法
[解决办法]
固定位数,位数不大,且为32或64的整数倍的,不要随便用任意长度大数运算(数组实现的),效率会比较低
[解决办法]
就用大数乘法,1楼那个竖式方法,
我也实现了一个,为了做题acm的,抠出来2个函数给你用
// 也可以用来计算任意长度整数/小数乘法,直接调用 string stringMul(string a, string b) 即可#include <iostream>#include <string>using namespace std;// 开关,是否显示竖式乘法运算步骤#define __MYDEBUG__ 1// 整理字符串,如果有小数点,去除右边多余0,如果没有,去除左边多余0// 返回小数位数*posstring cleanUp(string s,int *pos){ string result = s; size_t lpos,rpos,ppos; ppos = s.find("."); lpos = s.find_first_not_of("0"); rpos = s.find_last_not_of("0"); // 无小数点 if (ppos==string::npos) { *pos = 0; if (lpos==string::npos) result = "0"; else result = s.substr(lpos); } else { if (rpos==ppos) // 最右非0位是小数点,无小数位 { *pos = 0; if (lpos==ppos) // 如果最左非0也是小数点,是0.0 { result = "0"; } else // 否则是01.000类 { result = s.substr(lpos,ppos-lpos); } } else // 有小数位 { *pos = rpos-ppos; if (lpos==ppos) // 最左非0是小数点,截取小数点后部分继续判断最左非0位,0.0100类 { result = s.substr(ppos+1,rpos-ppos); lpos = result.find_first_not_of("0"); result = result.substr(lpos,rpos-lpos+1); } else // 否则直接拼接小数点左右部分,01.0100类 { result = s.substr(lpos,ppos-lpos)+s.substr(ppos+1,rpos-ppos); } } } return result;}// 字符串表示的大数相乘string stringMul(string a, string b){ int lena = a.size(); // a长度 int lenb = b.size(); // b长度 int pos = 0; // 错位数 int curmul = 0, // 当前计算结果 carry = 0, // 进位 curnum = 0; // 当前位数字. 关系: 当前计算结果=进位*10+当前位数字 // 最终计算结果结果肯定小于2个字符串长度之和 // 证明:长度为lena和lenb的2个数,最大可表示为10^lena-1和10^lenb-1 // (10^lena-1)*(10^lenb-1) = 10^(lena+lenb)-10^lena-10^lenb+1 < 10^(lena+lenb),证毕. string result = ""; result.insert(result.begin(),lena+lenb,'0'); string tempresult = ""; string current = "";#if (__MYDEBUG__) int wid = 40; char fm[20]; sprintf(fm,"%%%ds\n",wid); printf(fm,a.c_str()); sprintf(fm,"* %%%ds\n",wid-2); printf(fm,b.c_str()); printf("-----------------------------------------\n");#endif for (int i=lenb-1;i>=0;i--) { current = ""; // 当前字符串 carry = 0; // 进位 curnum = 0; // 要添加的字符 if ((int)(b[i]-'0')==0) { #if (__MYDEBUG__) sprintf(fm,"%%%ds\n",wid-pos); printf(fm,"0"); #endif pos++; continue; } for (int j=lena-1;j>=0;j--) { curmul = (int)(b[i]-'0')*(int)(a[j]-'0')+carry; carry = curmul/10; curnum = curmul%10; current.insert(current.begin(),1,(char)(curnum+'0')); } // 处理最后进位 while (carry>0) { current.insert(current.begin(),1,(char)(carry%10+'0')); carry /= 10; } #if (__MYDEBUG__) sprintf(fm,"%%%ds\n",wid-pos); printf(fm,current.c_str()); #endif // 添加给当前结果 if(result.empty()) { result = current; } else // 错位相加 { tempresult = ""; curmul = 0; carry = 0; curnum = 0; for (int i=(int)current.size()-1,j=(int)result.size()-1-pos;i>=0&&j>=0;i--,j--) { curmul = (int)(result[j]-'0')+(int)(current[i]-'0')+carry; carry = curmul/10; curnum = curmul%10; tempresult.insert(tempresult.begin(),1,(char)(curnum+'0')); } // 处理剩余的字符 while (carry>0) { tempresult.insert(tempresult.begin(),1,(char)(carry%10+'0')); carry /= 10; } // 添加给结果 result.replace((int)result.size()-(int)tempresult.size()-pos,(int)tempresult.size(),tempresult); } // 错位+1 pos++; } // 清理结果 int dummy = 0; result = cleanUp(result,&dummy);#if (__MYDEBUG__) printf("-----------------------------------------\n"); sprintf(fm,"%%%ds\n",wid); printf(fm,result.c_str());#endif return result;}