您的位置:首页 > 其它

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

2012-01-15 23:24 399 查看

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐