首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

128位乘除法如何算

2012-07-16 
128位乘除法怎么算?各位大大好,小弟现在写的是嵌入式程序,我的开发软件最大只支持64位数据(long long int)

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之间变化的,运算过程中不用浮点数。


[解决办法]
算法参考小学三年级乘除法竖式。(^_^)
仅供参考:

C/C++ code
#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个函数给你用

C/C++ code
// 也可以用来计算任意长度整数/小数乘法,直接调用 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;} 

热点排行
Bad Request.