实用算法实现-第 24 篇 高精度整数运算

来源:互联网 发布:ubuntu 16.04 u盘安装 编辑:程序博客网 时间:2024/05/08 20:15

24.1    高精度整数加法

24.1.1   实例

PKU JudgeOnline, 1503, Integer Inquiry.

24.1.2   问题描述

给定一组超长的正整数(100位),求出它们的和。

24.1.3   输入

123456789012345678901234567890

123456789012345678901234567890

123456789012345678901234567890

0

24.1.4   输出

370370367037037036703703703670

24.1.5   分析

写一个高精度的加法就可以了。这个题目的测试比较弱,或者说我曾经写的程序的错误很难通过这个题目的测试找出。因为在调试PKU JudgeOnline, 1131, Octal Fractions的程序的时候发现了这个高精度加法的一些bug,虽然它能通过这个题目的测试。

24.1.6   程序

#include<cstdio>#include<string.h>long s[10000005];#define __int64Max 3037000499//9223372030926249001 = 3037000499^2//9223372036854775808 = 2^63//9223372037000250000 = 3037000500^2#define MultiplyMaxDigit 8#define AddMaxDigit 18#define maxNum 7#define AddMaxNum 1000000000000000000//               1234567890123456789int main(){     __int64num[maxNum];     __int64 sum[maxNum];     charstr[102];     int numTop;     int sumTop;     int length;     int i;     int carry;     memset(sum, 0, sizeof(sum));     sumTop = 0;     while(scanf("%s", str) && strcmp(str, "0") != 0)     {         length = strlen(str);         numTop = 0;         memset(num, 0, sizeof(num));         while(length> AddMaxDigit)         {              length = length - AddMaxDigit;              sscanf(str + length, "%I64d", &num[numTop++]);              str[length] = '\0';         }         sscanf(str, "%I64d",&num[numTop]);         if(sumTop<= numTop)         {              sumTop = numTop;         }         carry = 0;         for(i =0; i <= numTop; i++){              sum[i] = num[i] + sum[i] + carry;              carry = 0;              if(sum[i]> AddMaxNum)              {                   sum[i] -= AddMaxNum;                   carry = 1;              }         }         if(carry== 1)         {sumTop++              sum[sumTop] = 1;         }     }     printf("%I64d",sum[sumTop]);     for(i =sumTop - 1; i >= 0; i--){         printf("%018I64d",sum[i]);     }     printf("\n");     return 1;}

24.2    高精度整数乘法

24.2.1   实例

PKU JudgeOnline, 1131, Octal Fractions

24.2.2   问题描述

实现八进制的小数到十进制的小数的转化,也即完成:0.d1d2d3 ...dk [8] = 0.D1D2D3 ... Dm [10]。

24.2.3   输入

0.75

0.0001

0.01234567

24.2.4   输出

0.75[8] = 0.953125 [10]

0.0001[8] = 0.000244140625 [10]

0.01234567 [8] =0.020408093929290771484375 [10]

24.2.5   分析

这个题目的测试也不是那么苛刻,因为不用高精度也能做。做着个题目的最大收获就是:随机测试是非常必要的。

24.2.6   程序

#include<cstdio>#include<string.h>#include<iostream>using namespace std;#define ONLINE_JUDGE 0#define __int64Max 3037000499//9223372030926249001 = 3037000499^2//9223372036854775808 = 2^63//9223372037000250000 = 3037000500^2#define MultiplyMaxDigit 9//#define AddMaxDigit 18#define maxNum 1000/*#define AddMaxNum 1000000000000000000//               1234567890123456789*/#define MultiplyMaxNum 1000000000//                    1234567890struct largeInt{     int top;     __int64num[maxNum];};void addLargeInt(largeInt *adder1, largeInt *adder2, largeInt*sum1){//adder和sum可以是同一个指针     int sumTop;     __int64sum[maxNum];     int carry;     int i;     memset(sum, 0, sizeof(sum));     sumTop = (*adder1).top;     if(sumTop< (*adder2).top)     {         sumTop = (*adder2).top;     }     carry = 0;     for(i = 0;i <= sumTop; i++){         sum[i] = (*adder1).num[i] +(*adder2).num[i] + carry;         carry = 0;         if(sum[i]>= MultiplyMaxNum)         {              sum[i] -= MultiplyMaxNum;              carry = 1;         }         if(sum[i]>= MultiplyMaxNum)         {              cout << "error" << endl;         }     }     if(carry ==1)     {         sumTop++;         sum[sumTop] = 1;     }     memcpy(&((*sum1).num), sum, sizeof(sum));     (*sum1).top = sumTop;}void multLargeInt(largeInt *mult1, largeInt *mult2, largeInt*product1){//adder和sum可以是同一个指针     intproductTop;     __int64product[maxNum];     __int64carry;     int i;     int j;     int k;     memset(product, 0, sizeof(product));     productTop = (*mult1).top + (*mult2).top +1;     carry = 0;     for(i = 0;i <= productTop; i++){         if(i<= (*mult1).top){              j = i;         }else{              j = (*mult1).top;         }         product[i] = carry;         carry = 0;         for(; j>= 0; j--){              k = i - j;              if(k> (*mult2).top)              {                   break;;              }              product[i] += (*mult1).num[j] *(*mult2).num[k];              if(product[i]> MultiplyMaxNum)              {                   carry += product[i] /MultiplyMaxNum;                   product[i] = product[i] %MultiplyMaxNum;              }         }     }     if(carry !=0)     {         product[productTop++] = carry;     }     while(product[productTop]== 0 && productTop != 0)     {         productTop--;     }     memcpy(&((*product1).num), product, sizeof(product));     (*product1).top = productTop;}void printLargeInt(largeInt *num){     int i;     printf("%I64d",(*num).num[(*num).top]);     for(i =(*num).top - 1; i >= 0; i--){         printf("%09I64d",(*num).num[i]);     }}void sprintLargeInt(largeInt *num, char* dst){     int i;     int length;     sprintf(dst, "%I64d",(*num).num[(*num).top]);     for(i =(*num).top - 1; i >= 0; i--){         length = strlen(dst);         sprintf(dst + length,"%09I64d", (*num).num[i]);     }}int main(){     #ifndefONLINE_JUDGE            FILE *fin;           fin = freopen("t.in", "r", stdin );       if( !fin )       {              printf( "reopen in filefailed...\n" );                while(1){}              return 0;       }        freopen( "ttest.out","w", stdout );     #endif      charstr[1000];     charbuff[1000];     int length;     largeInt constant;     largeInt power;     largeInt sum;     largeInt adder;     intlength1;     int i;     int start;     while(scanf("%s", str) != EOF)     {         length = strlen(str);         for(start= 2; str[start] == '0'; start++){              ;         }         start++;         memset(&constant.num, 0, sizeof(constant.num));         constant.num[0] = 125;         constant.top = 0;         memset(&power.num, 0, sizeof(power.num));         power.num[0] = 1;         power.top = 0;         memset(&sum.num, 0, sizeof(sum.num));         sum.top = 0;         for(i =0; i < length - 2; i++)         {              multLargeInt(&constant,&power, &power);         }         constant.num[0] = 8;         for(i =length - 1; i >= start - 1; i--){              memset(&adder.num, 0, sizeof(adder.num));              adder.top = 0;              adder.num[0] = str[i] - '0';              multLargeInt(&adder,&power, &adder);              addLargeInt(&adder, &sum,&sum);              multLargeInt(&constant,&power, &power);         }         printf("%s[8] = ", str);         printf("0.");         //printLargeInt(&sum);         sprintLargeInt(&sum, buff);         length1 = strlen(buff);         if(strcmp(buff,"0") != 0)         {              for(i= 0; i < (length - 2) * 3 - length1; i++)              {                   printf("0");              }              for(;length1 > 0; length1--){                   if(buff[length1- 1] != '0')                   {                       break;                   }              }              buff[length1] = '\0';              printf("%s",buff);         }         printf("[10]\n");     }     #ifndefONLINE_JUDGE            fclose( stdin );     #endif     return 1;}
本文章欢迎转载,请保留原始博客链接http://blog.csdn.net/fsdev/article

原创粉丝点击