[算法系列之八]大数问题(高精度运算)

【大数相加】

【代码一】
/*********************************
*   日期:2015-01-28
*   作者:SJF0115
*   题目: 大数加法(高精度加法)
*   博客:
**********************************/
#include 
using namespace std;

string AddString(string num1,string num2){
    int len1 = num1.length();
    int len2 = num2.length();
    // 容错处理
    if(len1 <= 0){
        return num2;
    }//if
    if(len2 <= 0){
        return num1;
    }
    string result;
    int i = len1-1,j = len2-1;
    int a,b,sum,carry = 0;
    // 倒序相加
    while(i >= 0 || j >= 0 || carry > 0){
        a = i >= 0 ? num1[i] - '0' : 0;
        b = j >= 0 ? num2[j] - '0' : 0;
        // 按位相加并加上进位
        sum = a + b + carry;
        // 进位
        carry = sum / 10;
        result.insert(result.begin(),sum % 10 + '0');
        --i;
        --j;
    }//while
    return result;
}


int main(){
    string num1("72");
    string num2("874");
    string result = AddString(num1,num2);
    // 输出
    cout<

【代码二】
/*********************************
*   日期:2015-01-28
*   作者:SJF0115
*   题目: 大数加法(高精度加法)
*   博客:
**********************************/
#include 
using namespace std;

string AddString(string num1,string num2){
    int len1 = num1.length();
    int len2 = num2.length();
    int max = len1 > len2 ? (len1 + 2) : (len2 + 2);
    char* result = new char[max];
    int index = 0;
    int i = len1 - 1,j = len2 - 1;
    int numA,numB,carry = 0,sum = 0;
    //加法
    while(i >= 0 || j >= 0 || carry > 0){
        numA = i >= 0 ? (num1[i] - '0') : 0;
        numB = j >= 0 ? (num2[j] - '0') : 0;
        sum = numA + numB + carry;
        carry = sum / 10;
        result[index++] = sum % 10 + '0';
        --i;
        --j;
    }//while
    result[index] = '\0';
    //反转
    for(i = 0,j = index - 1;i < j;++i,--j){
        char temp = result[i];
        result[i] = result[j];
        result[j] = temp;
    }//for
    return string(result);
}


int main(){
    string num1("872");
    string num2("874");
    string result = AddString(num1,num2);
    // 输出
    cout<

【代码三】

[cpp] view plain copy
  1. #include
  2. #include
  3. chara[10001],b[10001],sum[10002];
  4. intBigIntegerAdd(){
  5. //两个数的长度
  6. intlena=strlen(a);
  7. intlenb=strlen(b);
  8. //进位标记
  9. intc=0;
  10. inti,j,k;
  11. //初始化数组sum
  12. memset(sum,0,10001);
  13. //倒序相加
  14. k=0;
  15. for(i=lena-1,j=lenb-1;i>=0&&j>=0;i--,j--){
  16. sum[k]=a[i]+b[j]-'0'+c;
  17. c=0;
  18. //如果相加大于等于10
  19. if(sum[k]>'9'){
  20. sum[k]-=10;
  21. c=1;
  22. }
  23. k++;
  24. }
  25. //a>b
  26. while(i>=0){
  27. sum[k]=a[i]+c;
  28. c=0;
  29. //如果相加大于等于10
  30. if(sum[k]>'9'){
  31. sum[k]-=10;
  32. c=1;
  33. }
  34. k++;
  35. i--;
  36. }
  37. //b>a
  38. while(j>=0){
  39. sum[k]=b[j]+c;
  40. c=0;
  41. //如果相加大于等于10
  42. if(sum[k]>'9'){
  43. sum[k]-=10;
  44. c=1;
  45. }
  46. k++;
  47. j--;
  48. }
  49. //如果最后两个数相加有进位的情况
  50. //例如:67+51:5+6有进位
  51. if(c==1){
  52. sum[k++]='1';
  53. }
  54. //翻转
  55. chartemp;
  56. for(i=0,j=k-1;i
  57. temp=sum[i];
  58. sum[i]=sum[j];
  59. sum[j]=temp;
  60. }
  61. return0;
  62. }
  63. intmain(){
  64. while(scanf("%s%s",a,b)!=EOF){
  65. BigIntegerAdd();
  66. puts(sum);
  67. }
  68. }


【大数相减】

【代码一】
string MinusString(string num1, string num2) {
    int len1 = num1.length();
    int len2 = num2.length();
    // 相等
    if(num1 == num2){
        return "0";
    }//if
    // 正负
    bool positive = true;
    if(len1 < len2 || (len1 == len2 && num1 < num2)){
        positive = false;
        // 交换使之num1 > num2
        string tmp = num1;
        num1 = num2;
        num2 = tmp;
        int temp = len1;
        len1 = len2;
        len2 = temp;
    }//if
    string result;
    int i = len1 - 1,j = len2 - 1;
    int a,b,sum,carray = 0;
    // 从低位到高位对位做减法
    while(i >= 0 || j >= 0){
        a = i >= 0 ? num1[i] - '0' : 0;
        b = j >= 0 ? num2[j] - '0' : 0;
        sum = a - b + carray;
        carray = 0;
        // 不够减
        if(sum < 0){
            sum += 10;
            carray = -1;
        }//if
        result.insert(result.begin(),sum + '0');
        --i;
        --j;
    }//while
    // 删除前导0
    string::iterator it = result.begin();
    while(it != result.end() && *it == '0'){
        ++it;
    }//while
    result.erase(result.begin(),it);
    return positive ? result : "-"+result;
}

【代码二】

[cpp] view plain copy
  1. /*
  2. 1.比较减数与被减数的长度,确定正负号
  3. 2.模拟减法运算
  4. (1)a[i]==b[j]
  5. (2)a[i]
  6. (3)a[i]>b[j]
  7. */
  8. #include
  9. #include
  10. chara[10001],b[10001],sum[10001],temp[10001];
  11. intBigIntegerMinus(){
  12. //两个数的长度
  13. intlena=strlen(a);
  14. intlenb=strlen(b);
  15. //借位标记
  16. intc=0;
  17. inti,j,k,positive=1;
  18. //判断正负号
  19. if(lena
  20. strcpy(temp,a);
  21. strcpy(a,b);
  22. strcpy(b,temp);
  23. positive=-1;//负号
  24. lena=strlen(a);
  25. lenb=strlen(b);
  26. }
  27. //倒序相减
  28. k=0;
  29. for(i=lena-1,j=lenb-1;i>=0&&j>=0;i--,j--){
  30. sum[k]=a[i]-b[j]+'0'+c;
  31. c=0;
  32. //如果相减小于0
  33. if(sum[k]<'0'){
  34. sum[k]+=10;
  35. c=-1;
  36. }
  37. k++;
  38. }
  39. //a>b
  40. while(i>=0){
  41. sum[k]=a[i]+c;
  42. c=0;
  43. //如果相减小于0
  44. if(sum[k]<'0'){
  45. sum[k]+=10;
  46. c=-1;
  47. }
  48. k++;
  49. i--;
  50. }
  51. //b>a
  52. while(j>=0){
  53. sum[k]=b[j]+c;
  54. c=0;
  55. //如果相减小于0
  56. if(sum[k]<'0'){
  57. sum[k]+=10;
  58. c=-1;
  59. }
  60. k++;
  61. j--;
  62. }
  63. intindex=k-1;
  64. //检索高位,有可能相减为0
  65. while(sum[index]=='0'&&index>0){
  66. index--;
  67. }
  68. //正号
  69. if(positive==1){
  70. sum[index+1]='\0';
  71. }
  72. //负号
  73. else{
  74. sum[++index]='-';
  75. sum[index+1]='\0';
  76. }
  77. //翻转
  78. chart;
  79. for(i=0,j=index;i
  80. t=sum[i];
  81. sum[i]=sum[j];
  82. sum[j]=t;
  83. }
  84. return0;
  85. }
  86. intmain(){
  87. while(scanf("%s%s",a,b)!=EOF){
  88. BigIntegerMinus();
  89. puts(sum);
  90. }
  91. }

【大数乘法】

【代码一】
/*********************************
*   日期:2015-01-28
*   作者:SJF0115
*   题目: 高精度乘法(大数乘法)
*   博客:
**********************************/
#include 
#include 
using namespace std;

string MultiplyString(string num1, string num2) {
    int len1 = num1.length();
    int len2 = num2.length();
    // 容错处理
    if(len1 <= 0 || len2 <= 0){
        return "";
    }//if
    int sum = 0;
    int len3 = len1 + len2;
    char result[len3];
    memset(result,'0',sizeof(result[0])*(len3+1));
    for(int i = len1 - 1,m = 0;i >= 0;--i,++m){
        for(int j = len2 - 1,n = 0;j >= 0;--j,++n){
            sum = (num1[i] - '0') * (num2[j] - '0') + result[m+n] - '0';
            result[m+n] = sum % 10 + '0';
            // 进位
            result[m+n+1] += sum / 10;
        }//for
    }//for
    //去掉前导0 确定乘积的位数
    while(result[len3] == '0' && len3 > 0){
        --len3;
    }//while
    //注意:加'\0'
    result[len3+1] = '\0';
    //翻转
    int temp;
    for(int i = 0,j = len3;i < j;++i,--j){
        temp = result[i];
        result[i] = result[j];
        result[j] = temp;
    }//for
    return string(result);
}

int main(){
    string num1("2");
    string num2("123");
    string result = MultiplyString(num1,num2);
    // 输出
    cout<


【代码二】

[cpp] view plain copy
  1. #include
  2. #include
  3. chara[10001],b[10001],c[20002];
  4. intBigIntegerMulti()
  5. {
  6. inti,j,lena,lenb,lenc;
  7. //初始化
  8. memset(c,'0',20002);
  9. //两个数的长度
  10. lena=strlen(a);
  11. lenb=strlen(b);
  12. //乘积最大位数
  13. lenc=lena+lenb-1;
  14. //翻转
  15. chartemp;
  16. for(i=0,j=lena-1;i
  17. temp=a[i];
  18. a[i]=a[j];
  19. a[j]=temp;
  20. }
  21. for(i=0,j=lenb-1;i
  22. temp=b[i];
  23. b[i]=b[j];
  24. b[j]=temp;
  25. }
  26. //倒序相乘
  27. /*
  28. 123
  29. *54
  30. ------
  31. 492
  32. 615
  33. -----
  34. 6642
  35. */
  36. intt;
  37. for(i=0;i
  38. for(j=0;j
  39. /*c[i+j]=(a[i]-'0')*(b[j]-'0')+c[i+j];
  40. 9*9+'0'超出char范围越界所以设置一个int临时变量t*/
  41. t=(a[i]-'0')*(b[j]-'0')+c[i+j]-'0';
  42. //进位
  43. c[i+j+1]=t/10+c[i+j+1];
  44. c[i+j]=t%10+'0';
  45. }
  46. }
  47. //确定乘积的位数
  48. while(c[lenc]=='0'&&lenc>0){
  49. lenc--;
  50. }
  51. //注意:加'\0'
  52. c[lenc+1]='\0';
  53. //翻转
  54. for(i=0,j=lenc;i
  55. temp=c[i];
  56. c[i]=c[j];
  57. c[j]=temp;
  58. }
  59. return0;
  60. }
  61. intmain(){
  62. while(scanf("%s%s",a,b)!=EOF){
  63. BigIntegerMulti();
  64. puts(c);
  65. }
  66. return0;
  67. }

【代码三】

/*********************************
*   日期:2015-01-29
*   作者:SJF0115
*   题目: Karatsuba快速相乘算法
*   博客:
**********************************/
#include 
#include 
#include 
using namespace std;

// given two unequal sized bit strings, converts them to
// same length by adding leading 0s in the smaller string. Returns the
// the new length
int MakeSameLen(string& num1,string& num2){
    int len1 = num1.length();
    int len2 = num2.length();
    if(len1 < len2){
        for(int i = 0;i < len2 - len1;++i){
            num1 = "0" + num1;
        }//for
        return len2;
    }//if
    else{
        for(int i = 0;i < len1 - len2;++i){
            num2 = "0" + num2;
        }//for
        return len1;
    }//else
}
// big number minus function
string MinusString(string num1, string num2) {
    int len1 = num1.length();
    int len2 = num2.length();
    // 相等
    if(num1 == num2){
        return "0";
    }//if
    // 正负
    bool positive = true;
    if(len1 < len2 || (len1 == len2 && num1 < num2)){
        positive = false;
        // 交换使之num1 > num2
        string tmp = num1;
        num1 = num2;
        num2 = tmp;
        int temp = len1;
        len1 = len2;
        len2 = temp;
    }//if
    string result;
    int i = len1 - 1,j = len2 - 1;
    int a,b,sum,carray = 0;
    // 从低位到高位对位做减法
    while(i >= 0 || j >= 0){
        a = i >= 0 ? num1[i] - '0' : 0;
        b = j >= 0 ? num2[j] - '0' : 0;
        sum = a - b + carray;
        carray = 0;
        // 不够减
        if(sum < 0){
            sum += 10;
            carray = -1;
        }//if
        result.insert(result.begin(),sum + '0');
        --i;
        --j;
    }//while
    // 删除前导0
    string::iterator it = result.begin();
    while(it != result.end() && *it == '0'){
        ++it;
    }//while
    result.erase(result.begin(),it);
    return positive ? result : "-"+result;
}
// big number add function
string AddString(string num1,string num2){
    int len1 = num1.length();
    int len2 = num2.length();
    // 容错处理
    if(len1 <= 0){
        return num2;
    }//if
    if(len2 <= 0){
        return num1;
    }
    string result;
    int i = len1-1,j = len2-1;
    int a,b,sum,carry = 0;
    // 倒序相加
    while(i >= 0 || j >= 0 || carry > 0){
        a = i >= 0 ? num1[i] - '0' : 0;
        b = j >= 0 ? num2[j] - '0' : 0;
        // 按位相加并加上进位
        sum = a + b + carry;
        // 进位
        carry = sum / 10;
        result.insert(result.begin(),sum % 10 + '0');
        --i;
        --j;
    }//while
    return result;
}
// 移位
string ShiftString(string num,int len){
    if(num == "0"){
        return num;
    }//if
    for(int i = 0;i < len;++i){
        num += "0";
    }//for
    return num;
}
// Karatsuba快速相乘算法
string KaratsubaMultiply(string num1, string num2) {
    int len = MakeSameLen(num1,num2);
    if(len == 0){
        return 0;
    }//if
    // all digit are one
    if(len == 1){
        return to_string((num1[0] - '0')*(num2[0] - '0'));
    }//if
    int mid = len / 2;
    // Find the first half and second half of first string.
    string x1 = num1.substr(0,mid);
    string x0 = num1.substr(mid,len - mid);
    // Find the first half and second half of second string
    string y1 = num2.substr(0,mid);
    string y0 = num2.substr(mid,len - mid);
    // Recursively computer
    string z0 = KaratsubaMultiply(x0,y0);
    string z1 = KaratsubaMultiply(AddString(x1,x0),AddString(y1,y0));
    string z2 = KaratsubaMultiply(x1,y1);
    // (z2*10^(2*m))+((z1-z2-z0)*10^(m))+(z0)
    // z2*10^(2*m)
    string r1 = ShiftString(z2,2*(len - mid));
    // (z1-z2-z0)*10^(m)
    string r2 = ShiftString(MinusString(MinusString(z1,z2),z0),len - mid);
    return  AddString(AddString(r1,r2),z0);
}


int main(){
    string num1("12345001");
    string num2("1006789");
    string result = KaratsubaMultiply(num1,num2);
    // 输出
    cout<


自己写的如有问题,请告知一下。

你可能感兴趣的:([算法系列之八]大数问题(高精度运算))