按照上次的思路,最近又重新實現了加減法以及大數的乘法,除法的話,實現起來難度還有點大,有比較好的思路再來續寫吧。
#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 BigLen 10000 // length of the big number's array is BigLen
#define BigCarry 1000 // carry of the big number's array is BigCarry
/***
Assumption bigNum is a big number,
then the bigNum[0] is the lowest order digit while bigNum[BigLen-2] is the highest order digit and bigNum[BigLen-1] is sign bit.
bigNum[BigLen-1] is -1 means bigNum is a negative number while bigNum[BigLen-1] is 1 means bigNum is a positive number or zero.
We could define big number like this:
int bigNum[BigLen];
PS:I'm so sorry for my poor English.
*/
using namespace std;
bool add(int *sum, int *bigNum, int num);
bool add(int *sum, int *bigNumA, int *bigNumB);
int compare(int *bigNum,int num);
int compare(int *bigNumA,int *bigNumB);
int getTopPos(int *bigNum);
bool input(int *bigNum, char *str);
bool isBigNum(int *bigNum);
bool multiply(int *product, int *bigNum, int num);
bool multiply(int *product, int *bigNumA, int *bigNumB);
bool output(int *bigNum);
bool subtract(int *sub, int *bigNum, int num);
bool subtract(int *sub, int *bigNumA, int *bigNumB);
bool transBig2Num(int *bigNum, int &num);
bool transNum2Big(int *bigNum, int num);
bool isBigNum(int *bigNum)
{
/***
return true if the bigNum is legal big number while return false if not
*/
for(int i = 0; i < BigLen-1; ++i)
if(bigNum[i] < 0 || bigNum[i] >= BigCarry)
return false;
if(bigNum[BigLen-1] != 1 && bigNum[BigLen-1] != -1)
return false;
return true;
}
bool input(int *bigNum, char *str)
{
/***
giving a integer string and a pointer of array which length equal to BigLen
the integer string have to be made up of integer figure from 0 to 9 and character '-' which means negative number
the function will return true if the string is legal while return false if not
*/
int len = strlen(str);
if(len > (BigLen-1)*log10(BigCarry)) // the input string is too long so that the bigNum cannot save this number
return false;
int start = (str[0] == '-') ? 1 : 0;
bool isdigit = true;
for(int i = start; i < len; ++i){
if(str[i] < '0' || str[i] > '9'){
isdigit = false;
break;
}
}
if(!isdigit)
return false; // the input string have some non numerical character except '-'
int index = 0;
int num = 0;
int power = 1;
for(int i = len-1; i >= start; --i){
num += (str[i]-'0') * power;
power *= 10;
if(power == BigCarry){
bigNum[index++] = num;
num = 0;
power = 1;
}
}
if(num)
bigNum[index++] = num;
for(int i = index; i < BigLen-1; ++i)
bigNum[i] = 0;
bigNum[BigLen-1] = start ? -1 : 1;
if(bigNum[0] == 0 && getTopPos(bigNum) == 0) // this will be work if input the string like "-00000"
bigNum[BigLen-1] = 1;
return true;
}
bool multiply(int *product, int *bigNumA, int *bigNumB)
{
/***
computing the product of both bigNumA and bigNumB
*/
if(product != bigNumA && product != bigNumB){
int topPosB = getTopPos(bigNumB);
int productTemp[BigLen];
int carry;
mem(product);
product[BigLen-1] = 1;
for(int i = 0; i <= topPosB; ++i){
int num = bigNumB[i];
carry = 0;
mem(productTemp);
productTemp[BigLen-1] = 1;
for(int j = 0; j < BigLen-1; ++j){
carry += bigNumA[j] * num;
productTemp[j] = carry % BigCarry;
carry /= BigCarry;
}
if(carry) // return false if overflow
return false;
int topPosProductTemp = getTopPos(productTemp);
if(topPosProductTemp + i >= BigLen-1) // overflow
return false;
for(int j = BigLen-2; j >= i; --j)
productTemp[j] = productTemp[j-i];
for(int j = 0; j < i; ++j)
productTemp[j] = 0;
if(!add(product,product,productTemp))
return false;
}
delete productTemp;
product[BigLen-1] = bigNumA[BigLen-1] * bigNumB[BigLen-1];
return true;
}
else{
int productTemp[BigLen];
mem(productTemp);
if(!multiply(productTemp,bigNumA,bigNumB))
return false;
for(int i = 0; i < BigLen; ++i)
product[i] = productTemp[i];
delete productTemp;
return true;
}
}
bool multiply(int *product, int *bigNum, int num)
{
/***
computing the product of both bigNum and num
*/
int numSign;
num = (num >= 0) ? (numSign = 1 , num) : (numSign = -1 , -num);
if(num * BigCarry > inf){
int small[BigLen];
mem(small);
transNum2Big(small,num);
bool ans = multiply(product,bigNum,small);
delete small;
return ans;
}
else{
int carry = 0;
for(int i = 0; i < BigLen-1; ++i){
carry += bigNum[i] * num;
product[i] = carry % BigCarry;
carry /= BigCarry;
}
product[BigLen-1] = bigNum[BigLen-1] * numSign;
return carry ? false : true; // return false if overflow
}
}
bool subtract(int *sub, int *bigNum, int num)
{
/***
computing the different of both bigNum and num
*/
// 這個好麻煩啊→_→ 不想寫了,簡單調用一下吧。。。(using English cannot express my feelings)
// ignoring the above sentence, please
int small[BigLen];
mem(small);
transNum2Big(small,num);
bool ans = subtract(sub,bigNum,small);
delete small;
return ans;
}
bool add(int *sum, int *bigNum, int num)
{
/***
computing the sum of both bigNum and num
*/
if(bigNum[BigLen-1] == 1){
if(num >= 0){ // bigNum >= 0 && num >= 0
int carry = num / BigCarry;
int t = num % BigCarry + bigNum[0];
carry += t / BigCarry;
sum[0] = t % BigCarry;
for(int i = 1; i < BigLen-1; ++i){
t = carry + bigNum[i];
sum[i] = t % BigCarry;
carry = t / BigCarry;
}
sum[BigLen-1] = bigNum[BigLen-1];
return carry ? false : true; // return false if overflow
}
else{ // bigNum >= 0 && num < 0
return subtract(sum,bigNum,-num);
}
}
else{
if(num >= 0){ // bigNum < 0 && num >= 0
bigNum[BigLen-1] = 1;
bool ans = subtract(sum,bigNum,num);
if(bigNum != sum)
bigNum[BigLen-1] = -1;
sum[BigLen-1] *= -1;
return ans;
}
else{ // bigNum < 0 && num < 0
bigNum[BigLen-1] = 1;
bool ans = add(sum,bigNum,-num);
bigNum[BigLen-1] = -1;
sum[BigLen-1] = -1;
return ans;
}
}
}
bool subtract(int *sub, int *bigNumA, int *bigNumB)
{
/***
computing the difference of both bigNumA and bigNumB
*/
if(bigNumA[BigLen-1] == 1){
if(bigNumB[BigLen-1] == 1){ // bigNumA >= 0 && bigNumB >= 0
if(compare(bigNumA,bigNumB) >= 0){
int carry = 0;
for(int i = 0; i < BigLen-1; ++i){
carry += bigNumA[i] - bigNumB[i] + BigCarry;
sub[i] = carry % BigCarry;
carry = carry / BigCarry - 1;
}
sub[BigLen-1] = 1;
return carry ? false : true; // return false if overflow
}
else{
bool ans = subtract(sub,bigNumB,bigNumA);
sub[BigLen-1] = -1;
return ans;
}
}
else{ // bigNumA >=0 && bigNumB < 0
bigNumB[BigLen-1] = 1;
bool ans = add(sub,bigNumA,bigNumB);
if(bigNumB != sub)
bigNumB[BigLen-1] = -1;
return ans;
}
}
else{
if(bigNumB[BigLen-1] == 1){ // bigNumA < 0 && bigNumB >=0
bigNumA[BigLen-1] = 1;
bool ans = add(sub,bigNumA,bigNumB);
bigNumA[BigLen-1] = -1;
sub[BigLen-1] = -1;
return ans;
}
else{ // bigNumA < 0 && bigNumB < 0
bigNumA[BigLen-1] = 1;
bigNumB[BigLen-1] = 1;
bool ans = subtract(sub,bigNumB,bigNumA);
if(bigNumB != sub)
bigNumB[BigLen-1] = -1;
if(bigNumA != sub)
bigNumA[BigLen-1] = -1;
return ans;
}
}
}
bool add(int* sum, int *bigNumA, int *bigNumB)
{
/***
computing the sum of both bigNumA and bigNumB
*/
if(bigNumA[BigLen-1] == bigNumB[BigLen-1]){ // both bigNumA and bigNumB are negative or positive numbers
int carry = 0;
for(int i = 0; i < BigLen-1; ++i){
carry += bigNumA[i] + bigNumB[i];
sum[i] = carry % BigCarry;
carry /= BigCarry;
}
sum[BigLen-1] = bigNumA[BigLen-1];
return carry ? false : true; // return false if overflow
}
else{
if(bigNumA[BigLen-1] == -1){
bigNumA[BigLen-1] = 1;
bool ans = subtract(sum,bigNumB,bigNumA);
if(bigNumA != sum)
bigNumA[BigLen-1] = -1;
return ans;
}
else{
bigNumB[BigLen-1] = 1;
bool ans = subtract(sum,bigNumA,bigNumB);
if(bigNumB != sum)
bigNumB[BigLen-1] = -1;
return ans;
}
}
}
bool transNum2Big(int *bigNum, int num)
{
/***
transferring a integer number to bigNum
*/
bigNum[BigLen-1] = (num >= 0 ? 1 : -1);
num = (num >= 0 ? num : -num);
int index = 0;
while(num > 0){
bigNum[index++] = num % BigCarry;
num /= BigCarry;
}
return true;
}
bool transBig2Num(int *bigNum, int &num)
{
/***
transferring a bigNum to a integer number
*/
int topPos = getTopPos(bigNum);
if(int(topPos*log10(BigCarry) + log10(bigNum[topPos])) >= int(log10(inf)))
return false; // return false if this num is not less than 1,000,000,000, but actually the biggest integer is 2,147,483,647(that is inf)
num = bigNum[BigLen-1];
num = num*bigNum[topPos];
for(int i = topPos-1; i >= 0; --i)
num = num*BigCarry + bigNum[i];
return true;
}
int compare(int *bigNum, int num)
{
/***
if bigNum > num, then return 1
if bigNum = num, then return 0
if bigNum < num, then return -1
*/
int bigSign = bigNum[BigLen-1];
if(bigSign * num >= 0){
int topPos = getTopPos(bigNum);
int bigDigits = topPos*log10(BigCarry) + log10(bigNum[topPos]);
int numDigits = log10(num);
if(bigDigits != numDigits)
return bigDigits > numDigits ? bigSign : -bigSign;
int big;
if(transBig2Num(bigNum,big)){
if(big != num)
return big > num ? 1 : -1;
else
return 0;
}
else{
int small[BigLen];
mem(small);
transNum2Big(small,num);
int ans = compare(bigNum,small);
delete small;
return ans;
}
}
else{
return num > 0 ? -1 : 1;
}
}
int compare(int *bigNumA,int *bigNumB)
{
/***
if bigNumA > bigNumB, then return 1
if bigNumA = bigNumB, then return 0
if bigNumA < bigNumB, then return -1
*/
if(bigNumA[BigLen-1] != bigNumB[BigLen-1])
return bigNumA[BigLen-1] > bigNumB[BigLen-1] ? 1 : -1;
// both bigNumA and bigNumB are positive numbers or negative numbers
int sign = bigNumA[BigLen-1];
int topPosA = getTopPos(bigNumA);
int topPosB = getTopPos(bigNumB);
if(topPosA != topPosB)
return topPosA > topPosB ? sign : -sign ;
for(int i = topPosA; i >= 0; --i)
if(bigNumA[i] != bigNumB[i])
return bigNumA[i] > bigNumB[i] ? sign : -sign ;
return 0;
}
int getTopPos(int *bigNum)
{
/***
return the array index of bigNum's highest digits
return 0 if the bigNum is zero
*/
for(int topPos = BigLen-2; topPos >= 0; --topPos)
if(bigNum[topPos])
return topPos;
return 0;
}
bool output(int *bigNum)
{
/***
output big number bigNum and carriage return is followed
*/
if(!isBigNum(bigNum))
return false;
int topPos = getTopPos(bigNum);
if(bigNum[BigLen-1] == -1 && (topPos || bigNum[topPos]))
printf("-");
printf("%d",bigNum[topPos]);
char formatLen[2] = {char(log10(BigCarry)) + '0'};
char format[6] = "%0";
strcat(format,formatLen);
strcat(format,"d");
for(int i = topPos-1; i >= 0; --i)
printf(format,bigNum[i]);
printf("\n");
return true;
}
歡迎各界大佬指出bug,非常感謝!