wikioi-天梯-提高一等-高精度普及-3118:高精度练习之除法

来源:互联网 发布:mac快捷键最小化 编辑:程序博客网 时间:2024/05/16 09:50

给出两个正整数A和B,计算A/B整数部分的值。保证A和B的位数不超过500位。

读入两个用空格隔开的正整数

输出A/B整数部分的值

15 4

3

两个正整数的位数不超过500位

类型:高精度  难度:2.5

题意:给出两个整数(500位以内)A,B,求A/B的结果的整数部分

分析:高精度除法,做下来看的话,感觉涉及的内容还比较多,步骤如下:

1、若A小于B,直接返回0,否则进入下一步

2、计算B的0-10倍数,存储在数组bt中(此时用到高精度加法)

3、用now记录A当前被除数运算部分,将now初始化为A.substr(0,B.length()),即A从左开始截取B长度的子串,若now比B小,则now末尾再加A的下一位

4、将now看成被除数的窗,不断右移直到A的末尾,模拟除法运算,每次用now和bt[i](1<=i<=10)作比较,直到bt[i]>now,那么i-1就是当前位的商,加入结果字符串c的末尾

5、更新now,now=now-bt[i-1](此处用到高精度减法)然后将被除数窗右移一位,即now末尾加上A串的下一位

注意:

1、若now为0的话,我用空字符串记录,所以第5步窗移的时候要判断,特殊处理,高精度减法的时候也要特殊处理

2、去掉string类型字符串末尾的字符,若用a[a,length()-1] = '\0',那么a.length()不会改变,必须用a = a.substr(0,a.length()-1),这是一个string的用法小技巧


代码:

#include<iostream>#include<string>using namespace std;string rev(string a){    string ret = a;    int n = a.length();    for(int i=0; i<n/2; i++)    {        char tmp = ret[i];        ret[i] = ret[n-i-1];        ret[n-i-1] = tmp;    }    return ret;}string add(string a,string b){    int la = a.length();    int lb = b.length();        a = rev(a);    b = rev(b);        int carry = 0;    string c;    int i;    for(i=0; i<la && i<lb; i++)    {        int ai = a[i]-'0';        int bi = b[i]-'0';        int ci = ai+bi+carry;        c += (ci%10)+'0';        carry = ci/10;    }    for(; i<la; i++)    {        int ai = a[i]-'0';        int ci = ai+carry;        c += (ci%10)+'0';        carry = ci/10;    }    for(; i<lb; i++)    {        int bi = b[i]-'0';        int ci = bi+carry;        c += (ci%10)+'0';        carry = ci/10;    }    if(carry) c += '1';    return rev(c);}string sub(string a,string b){    int la = a.length();    int lb = b.length();        if(la<lb || (la==lb && a<b))        return "";        a = rev(a);    b = rev(b);        int carry = 0;    string c;    int i;    for(i=0; i<la && i<lb; i++)    {        int ai = a[i]-'0';        int bi = b[i]-'0';        int ci = ai-bi-carry;        if(ci<0)        {            ci += 10;            carry = 1;        }        else            carry = 0;        c += (ci%10)+'0';    }    for(; i<la; i++)    {        int ai = a[i]-'0';        int ci = ai-carry;        if(ci<0)        {            ci += 10;            carry = 1;        }        else            carry = 0;        c += (ci%10)+'0';    }        int lc = c.length();    for(i=c.length()-1; i>=0; i--)    {        if(c[i]=='0') lc--;        else break;    }    if(lc==0) return "";    c = c.substr(0,lc);    return rev(c);}string divide(string a,string b){    int la = a.length();    int lb = b.length();        if(la<lb || (la==lb && a<b))        return "0";        string bt[11];    bt[0] = "";    bt[1] = b;    for(int j=2; j<=10; j++)    {        bt[j] = add(bt[j-1],bt[1]);        //cout<<rev(s[j])<<endl;    }        int i = lb-1;    string c;    string now = a.substr(0,lb);    if(now<b)    {        now += a[++i];    }        for(; i<la; i++)    {        int ci;        int lnow = now.length();                for(ci=1; ci<=10; ci++)        {            int lbn = bt[ci].length();            if(lbn>lnow || (lbn==lnow && bt[ci]>now))                break;        }        ci--;        c += ci+'0';                now = sub(now,bt[ci]);                if(i<la-1)        {            if(now.size()==0 && a[i+1]=='0')                continue;            now += a[i+1];        }    }    return c;}int main(){    string a,b;    cin>>a>>b;    cout<<divide(a,b)<<endl;}



0 0
原创粉丝点击