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

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
//               1234567890123456789
int 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
//                    1234567890
struct 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值