今天想試着實現了一些C++大數的操作,忙活的時間不少,只不過就實現了加減法,乘除的方法只能有時間再來實現了。
說點心得,我下面大數的存儲方式很蠢(起初沒想着實現負數 後來寫減法的時候就想着也把負數的實現了 實現起來的時候才發現自己給自己挖了一個大坑),下次實現大數的話,符號估計會單獨存儲,這樣處理乘除法也比較方便。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#define mem(array) memset((array),0,sizeof((array)))
#define Qsort(array,len,cmp) qsort(array,len,sizeof(array[0]),cmp)
#define inf 0x7fffffff
#define MAXN 1000
#define BigLen 1000
#define BigCarry 1000
using namespace std;
int compareBig(int *a, int *b);
int getTopDigits(int *a);
int getBigLen(int *a);
int* addBig(int *sum,int *a, int *b);
int* addSmall(int *sum,int *big, int small);
int* subtractBig(int *sub,int *a,int *b);
int* subtractSmall(int *sub,int *big, int small);
int outputBig(int *a);
int compareBig(int *a, int *b) /*** if a > b then return 1 while return -1 when a < b ,other case(a = b) return 0 */
{
int aTopDigits = getTopDigits(a);
int bTopDigits = getTopDigits(b);
if(aTopDigits < 0 && bTopDigits > 0) /*** a is a negative number while b is a positive number */
return -1;
else if(aTopDigits > 0 && bTopDigits < 0) /*** a is a positive number while b is a negative number */
return 1;
/*** both a and b are negative number or positive number */
int aLen = getBigLen(a);
int bLen = getBigLen(b);
int flag = (aTopDigits>0 ? 1 : -1);
if(aLen < bLen)
return -flag;
else if(aLen > bLen)
return flag;
else{
if(a[aLen] < b[aLen])
return -1;
else if(a[aLen] > b[aLen])
return 1;
for(int i = aLen-1; i >= 0; --i){
if(a[i] < b[i])
return -flag;
else if(a[i] > b[i])
return flag;
}
}
return 0;
}
int getTopDigits(int *a)
{
for(int i = BigLen-1; i >= 0; --i){
if(a[i])
return a[i];
}
}
int getBigLen(int *a)
{
int cnt;
for(cnt = BigLen-1; cnt >= 0; --cnt){
if(a[cnt])
return cnt+1;
//break;
}
/***
int digits;
if(abs(a[cnt]) >= 100)
digits = 3;
else if(abs(a[cnt]) >= 10)
digits = 2;
else if(abs(a[cnt]) >= 0)
digits = 1;
else
return -1;
digits += cnt*(int)log10(BigLen);
return digits;
*/
}
int* addBig(int *sum,int *a, int *b) /*** sum = a + b */
{
int aTopDigits = getTopDigits(a);
int bTopDigits = getTopDigits(b);
if(aTopDigits >= 0 && bTopDigits >= 0){ /*** a is a positive number while b is a positive number*/
int t;
int carry = 0;
for(int i = 0; i < BigLen; ++i){
t = a[i] + b[i] + carry;
sum[i] = t % BigCarry;
carry = t / BigCarry;
}
return sum;
}
else if(aTopDigits >= 0 && bTopDigits < 0){ /*** a is a positive number while b is a negative number*/
int *t = new int[BigLen];
for(int i = 0; i < BigLen; ++i)
t[i] = b[i];
int index = getBigLen(t)-1;
t[index] = -t[index];
subtractBig(sum,a,t);
delete t;
return sum;
}
else if(aTopDigits < 0 && bTopDigits >= 0){ /*** a is a negative number while b is a positive number*/
return addBig(sum,b,a);
}
else if(aTopDigits < 0 && bTopDigits < 0){ /*** a is a negative number while b is a negative number*/
int *t1 = new int[BigLen];
int *t2 = new int[BigLen];
for(int i = 0; i < BigLen; ++i){
t1[i] = a[i];
t2[i] = b[i];
}
int index_1 = getBigLen(t1)-1;
int index_2 = getBigLen(t2)-1;
t1[index_1] = -t1[index_1];
t2[index_2] = -t2[index_2];
addBig(sum,t1,t2);
delete t1,t2;
int index = getBigLen(sum) - 1;
sum[index] = -sum[index];
return sum;
}
}
int* addSmall(int *sum,int *big, int small) /**** sum = big + small , compute a big number and a small number , big number must be greater than 0 */
{
if(small < 0)
return subtractSmall(sum,big,-small);
int t = small % BigCarry;
int carry = small / BigCarry;
int index;
for(index = 0; (t||carry) && index < BigLen; ++index){
t += big[index];
sum[index] = t % BigCarry;
carry += t / BigCarry;
t = carry % BigCarry;
carry /= BigCarry;
}
while(index < BigLen)
sum[index] = big[index++];
return sum;
}
int* subtractBig(int *sub,int *a,int *b) /*** sub = a - b */
{
int aTopDigits = getTopDigits(a);
int bTopDigits = getTopDigits(b);
if(aTopDigits >= 0 && bTopDigits >= 0){ /*** a is a positive number while b is a positive number*/
int t;
int carry = 0;
for(int i = 0; i < BigLen; ++i){
t = a[i] - b[i] - carry;
t >= 0 ? carry = 0 : (carry = 1,t += BigCarry);
sub[i] = t;
}
if(carry){
for(int i = 0; i < BigLen; ++i)
sub[i] = BigLen - sub[i] - 1;
addSmall(sub,sub,1);
for(int i = BigLen-1; i >= 0; --i)
if(sub[i]){
sub[i] = -sub[i];
break;
}
}
return sub;
}
else if(aTopDigits >= 0 && bTopDigits < 0){ /*** a is a positive number while b is a negative number*/
int *t = new int[BigLen];
for(int i = 0; i < BigLen; ++i)
t[i] = b[i];
int index = getBigLen(t)-1;
t[index] = -t[index];
addBig(sub,a,t);
delete t;
return sub;
}
else if(aTopDigits < 0 && bTopDigits >= 0){ /*** a is a negative number while b is a positive number*/
int *t = new int[BigLen];
for(int i = 0; i < BigLen; ++i)
t[i] = a[i];
int index = getBigLen(t)-1;
t[index] = -t[index];
addBig(sub,t,b);
delete t;
index = getBigLen(sub) - 1;
sub[index] = -sub[index];
return sub;
}
else if(aTopDigits < 0 && bTopDigits < 0){ /*** a is a negative number while b is a negative number*/
int *t1 = new int[BigLen];
int *t2 = new int[BigLen];
for(int i = 0; i < BigLen; ++i){
t1[i] = a[i];
t2[i] = b[i];
}
int index_1 = getBigLen(t1) - 1;
int index_2 = getBigLen(t2) - 1;
t1[index_1] = -t1[index_1];
t2[index_2] = -t2[index_2];
subtractBig(sub,t2,t1);
delete t1,t2;
return sub;
}
}
int* subtractSmall(int *sub,int *big, int small) /**** sub = big - small , compute a big number and a small number , big number must be greater than 0 */
{
if(small < 0)
return addSmall(sub,big,-small);
int t = small % BigCarry;
int carry = small / BigCarry;
int index;
for(index = 0; (t||carry) && index < BigLen; ++index){
sub[index] = big[index] - t;
/** sub[index] < 0 ? (sub[index] += BigCarry , ++carry) : ; */
if(sub[index] < 0){
sub[index] += BigCarry;
++carry;
}
t = carry % BigCarry;
carry /= BigCarry;
}
while(index < BigLen)
sub[index] = big[index++];
return sub;
}
int outputBig(int *a)
{
int index = -1;
for(int i = BigLen-1; i >= 0; --i)
if(a[i] != 0){
index = i;
printf("%d",a[i]);
break;
}
for(int i = index-1; i >= 0; --i)
printf("%03d",a[i]);
if(index == -1)
cout<<0;
cout<<endl;
}
int a[MAXN];
int b[MAXN];
int c[MAXN];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
mem(a);
mem(b);
mem(c);
for(int i = 0; i < 10; ++i){
a[i] = 555;
b[i] = 555;
}
b[0] = 556;
//b[10] = -1;
a[10] = -1;
//addBig(c,a,b);
subtractBig(c,a,b);
//cout<<compareBig(a,b)<<endl;
//cout<<getTopDigits(a)<<endl;
//cout<<getBigLen(a)<<endl;
//addSmall(c,a,-566);
//subtractSmall(c,a,0);
//outputBig(c);
//subtractBig(c,a,b);
//subtractSmall(b,a,9999);
//subtractSmall(a,a,999);
outputBig(a);
outputBig(b);
outputBig(c);
return 0;
}