/*
Name: 高精度整數(shù)運(yùn)算改進(jìn)版
Copyright:始發(fā)于goal00001111的專欄;允許自由轉(zhuǎn)載,但必須注明作者和出處
Author: goal00001111
Date: 15-12-08 08:18
Description:
高精度整數(shù)運(yùn)算:加減乘除,乘方,階乘 。
上次寫了一個(gè)用字符串存儲(chǔ)高精度整數(shù)的四則運(yùn)算算法,雖然可以實(shí)現(xiàn)功能,但時(shí)間復(fù)雜度和空間復(fù)雜度都不夠理想,
這次出了個(gè)改進(jìn)版,將原來(lái)的用字符串存儲(chǔ)改成用整型數(shù)組存儲(chǔ),而且改進(jìn)了乘法,除法和乘方的算法,更快更高效!
*/
#include<iostream>
#include<string>
using namespace std;
const unsigned int MAX = 10000; //整型數(shù)組的最大長(zhǎng)度
const long long WIDTHMAX = 1000000000; //整型數(shù)組val[MAX]的元素上限
const unsigned int WIDTH = 9; //輸出整型數(shù)組val[MAX]的元素時(shí)的格式寬度,即整型數(shù)組val[MAX]的元素的最多位數(shù)
typedef struct node
{
long long val[MAX]; //用來(lái)存儲(chǔ)高精度整數(shù)
unsigned int size; //整型數(shù)組的實(shí)際長(zhǎng)度
} BigInt;
BigInt StrToBigInt(string s);
void PrintBigInt(const BigInt & a);
int ComPareBigInt(const BigInt & a, const BigInt & b);
BigInt MulBigInt(const BigInt & a, const BigInt & b);
BigInt AddBigInt(const BigInt & a, const BigInt & b);
BigInt SubBigInt(BigInt a, BigInt b);
BigInt DivBigInt(const BigInt & a, const BigInt & b);
BigInt FacBigInt(unsigned int n);
void PowBigInt(BigInt & c, const BigInt & a, unsigned int n);
void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n);
BigInt HalfBigInt(BigInt a);
int main()
{
string s;
BigInt a, b, c;
cin >> s;
a = StrToBigInt(s);
cin >> s;
b = StrToBigInt(s);
cout << " ";
PrintBigInt(a);
cout << "+ ";
PrintBigInt(b);
c = AddBigInt(a, b);
cout << "= ";
PrintBigInt(c);
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "- ";
PrintBigInt(b);
c = SubBigInt(a, b);
cout << "= ";
PrintBigInt(c);
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "* ";
PrintBigInt(b);
c = MulBigInt(a, b);
cout << "= ";
PrintBigInt(c);
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "/ 2 " << endl;
c = HalfBigInt(a);
cout << "= ";
PrintBigInt(c);
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "/ ";
PrintBigInt(b);
c = DivBigInt(a, b);
cout << "= ";
PrintBigInt(c);
cout << endl;
unsigned int n;
cin >> n;
//cout << n << "! = ";
// c = FacBigInt(n);
// PrintBigInt(c);
// cout << c.size << endl;
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "^" << n << " = ";
PowBigInt(c, a, n);
PrintBigInt(c);
cout << endl;
cout << " ";
PrintBigInt(a);
cout << "^" << n << " = ";
PowBigInt_2(c, a, n);
PrintBigInt(c);
cout << endl;
system("pause");
return 0;
}
/*
函數(shù)名稱:PrintBigInt
函數(shù)功能:輸出用整型數(shù)組表示的高精度整數(shù)
輸入?yún)?shù):const BigInt & a:用整型數(shù)組表示的高精度整數(shù)
輸出參數(shù):無(wú)
*/
void PrintBigInt(const BigInt & a)
{
cout << a.val[a.size-1];
for (int i=a.size-2; i>=0; i--)
{
unsigned w = WIDTHMAX / 10;
while (w > 0)
{
if (a.val[i] >= w)
break;
cout << 0;
w /= 10;
}
cout << a.val[i];
}
cout << endl;
}
/*
函數(shù)名稱:StrToBigInt
函數(shù)功能:把元素為數(shù)字的字符串轉(zhuǎn)換為用整型數(shù)組表示的高精度整數(shù)
輸入?yún)?shù):string s:存儲(chǔ)數(shù)字的字符串
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)
*/
BigInt StrToBigInt(string s)
{
BigInt a;
a.size = 0;
int i = s.size();
unsigned long long sum = 0;
while ( i>=WIDTH)
{
for (int j=i-WIDTH; j<i; j++)
sum = sum * 10 + (s[j] - '0');
a.val[a.size++] = sum;
sum = 0;
i -= WIDTH;
}
if (i > 0)
{
for (int j=0; j<i; j++)
sum = sum * 10 + (s[j] - '0');
a.val[a.size++] = sum;
}
return a;
}
/*
函數(shù)名稱:AddBigInt
函數(shù)功能:高精度整數(shù)加法
輸入?yún)?shù):const BigInt & a:用整型數(shù)組表示的高精度整數(shù)加數(shù)
const BigInt & b:用整型數(shù)組表示的高精度整數(shù)加數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)和
*/
BigInt AddBigInt(const BigInt & a, const BigInt & b)
{
//逆序計(jì)算a+b,則從低位開(kāi)始計(jì)算
BigInt c;
unsigned long long carry = 0;
unsigned int i = 0;
c.size = 0;
while (i < a.size && i < b.size)
{
c.val[c.size++] = (a.val[i] + b.val[i] + carry) % WIDTHMAX;
carry = (a.val[i] + b.val[i] + carry) / WIDTHMAX;
i++;
}
while (i < a.size)
{
c.val[c.size++] = (a.val[i] + carry) % WIDTHMAX;
carry = (a.val[i] + carry) / WIDTHMAX;
i++;
}
while (i < b.size)
{
c.val[c.size++] = (b.val[i] + carry) % WIDTHMAX;
carry = (b.val[i] + carry) / WIDTHMAX;
i++;
}
if (carry > 0)
c.val[c.size++] = carry;
return c;
}
/*
函數(shù)名稱:SubBigInt
函數(shù)功能:高精度整數(shù)減法
輸入?yún)?shù):BigInt a:用整型數(shù)組表示的高精度整數(shù)被減數(shù)
BigInt b:用整型數(shù)組表示的高精度整數(shù)減數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)差
*/
BigInt SubBigInt(BigInt a, BigInt b)
{
BigInt c;
c.size = 0;
if (ComPareBigInt(a, b) == 0)
{
c.size = 1;
c.val[0] = 0;
return c;
}
bool flag = false;
if (ComPareBigInt(a, b) < 0)//交換,并得到一個(gè)負(fù)號(hào)
{
flag = true;
BigInt temp = a;
a = b;
b = temp;
}
unsigned int i = 0;
while (i < b.size)
{
if (a.val[i] >= b.val[i])
c.val[c.size++] = a.val[i] - b.val[i];
else
{
a.val[i+1] -= 1;
c.val[c.size++] = a.val[i] + WIDTHMAX - b.val[i];
}
i++;
}
while (i < a.size)
{
if (a.val[i] < 0)
{
a.val[i+1] -= 1;
a.val[i] += WIDTHMAX;
}
c.val[c.size++] = a.val[i];
i++;
}
//消除多余的高位0
while (c.val[c.size-1] == 0)
c.size--;
if (flag)//如果是負(fù)數(shù),加上負(fù)號(hào)
c.val[c.size-1] = -c.val[c.size-1];
return c;
}
/*
函數(shù)名稱:ComPareBigInt
函數(shù)功能:比較兩個(gè)高精度整數(shù)的大小
輸入?yún)?shù):BigInt a:用整型數(shù)組表示的高精度整數(shù)被減數(shù)
BigInt b:用整型數(shù)組表示的高精度整數(shù)減數(shù)
輸出參數(shù):int:a > b返回1,a = b返回0,a < b返回-1
*/
int ComPareBigInt(const BigInt & a, const BigInt & b)
{
if (a.size > b.size)
return 1;
if (a.size < b.size)
return -1;
for (int i=a.size-1; i>=0; i--)
{
if (a.val[i] > b.val[i])
return 1;
if (a.val[i] < b.val[i])
return -1;
}
return 0;
}
/*
函數(shù)名稱:MulBigInt
函數(shù)功能:高精度整數(shù)乘法
輸入?yún)?shù):const BigInt & a:用整型數(shù)組表示的高精度整數(shù)被乘數(shù)
const BigInt & b:用整型數(shù)組表示的高精度整數(shù)乘數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)乘積
*/
BigInt MulBigInt(const BigInt & a, const BigInt & b)
{
if (a.size == 1 && a.val[0] == 0)
return a;
if (b.size == 1 && b.val[0] == 0)
return b;
BigInt c;
for (int i=0; i<MAX; i++) //全部賦初值為0
c.val[i] = 0;
for (int i=0, j=0; i<b.size; i++)
{
for (j=0; j<a.size; j++)
{
c.val[i+j] += a.val[j] * b.val[i];
c.val[i+j+1] += c.val[i+j] / WIDTHMAX;
c.val[i+j] %= WIDTHMAX;
}
c.size = i + j;
if (c.val[c.size] != 0)//最高位有進(jìn)位
c.size++;
}
return c;
}
/*
老版本:
BigInt MulBigInt2(const BigInt & a, const BigInt & b)
{
if (a.size == 1 && a.val[0] == 0)
return a;
if (b.size == 1 && b.val[0] == 0)
return b;
BigInt c, tc;
unsigned long long carry = 0;
c.size = 0;
for (int i=0, j=0; i<b.size; i++)
{
for (j=0; j<i; j++)//先在臨時(shí)和tc的低位補(bǔ)足0
tc.val[j] = 0;
carry = 0;
for (j=0; j<a.size; j++)
{
tc.val[i+j] = (a.val[j] * b.val[i] + carry) % WIDTHMAX;
carry = (a.val[j] * b.val[i] + carry) / WIDTHMAX;
}
tc.size = i + j;
if (carry > 0)
tc.val[tc.size++] = carry;
//累加到c中
c = AddBigInt(tc, c);
}
return c;
}
*/
/*
函數(shù)名稱:FacBigInt
函數(shù)功能:高精度整數(shù)階乘
輸入?yún)?shù):unsigned int n:正整數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)階乘
*/
BigInt FacBigInt(unsigned int n)
{
BigInt s, c;
c.size = s.size = 1;
s.val[0] = 1;
for (unsigned long long i=2; i<=n; i++)
{
c.val[0] = i;
s = MulBigInt(s, c);
}
return s;
}
/*
函數(shù)名稱:PowBigInt
函數(shù)功能:遞歸高效算法求高精度整數(shù)冪
輸入?yún)?shù):BigInt & c:存儲(chǔ)高精度整數(shù)冪的整型數(shù)組
const BigInt & a:用整型數(shù)組表示的高精度整數(shù)底數(shù)
long long n: 指數(shù)
*/
void PowBigInt(BigInt & c, const BigInt & a, unsigned int n)
{
if (n == 1)
{
c = a;
return ;
}
if (n == 0 || (a.size == 1 && a.val[0] == 1))
{
c.size = c.val[0] = 1;
return ;
}
PowBigInt(c, a, n/2); //遞歸求高精度整數(shù)冪
c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a)
if (n % 2 == 1) //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)
c = MulBigInt(a, c);
}
/*
函數(shù)名稱:PowBigInt_2
函數(shù)功能:非遞歸高效算法求高精度整數(shù)冪
輸入?yún)?shù):BigInt & c:存儲(chǔ)高精度整數(shù)冪的整型數(shù)組
const BigInt & a:用整型數(shù)組表示的高精度整數(shù)底數(shù)
long long n: 指數(shù)
*/
void PowBigInt_2(BigInt & c, const BigInt & a, unsigned int n)
{
int stack[MAX] = {0};
int top = 0;
while (n > 0) //利用一個(gè)棧來(lái)存儲(chǔ)n的狀態(tài):奇數(shù)還是偶數(shù)
{
stack[top++] = n % 2;
n /= 2;
}
c.size = c.val[0] = 1;
for (int i=top-1; i>=0; i--)
{
c = MulBigInt(c, c); //a^n = a^(n/2)*a^(n/2)*f(a)
if (stack[i] == 1) //其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)
c = MulBigInt(a, c);
}
}
/*
函數(shù)名稱:DivBigInt
函數(shù)功能:二分法實(shí)現(xiàn)高精度整數(shù)除法
輸入?yún)?shù):const BigInt & a:用整型數(shù)組表示的高精度整數(shù)被除數(shù)
const BigInt & b:用整型數(shù)組表示的高精度整數(shù)除數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)商
*/
BigInt DivBigInt(const BigInt & a, const BigInt & b)
{
BigInt high, low, mid, one, c;
if ((a.size == 1 && a.val[0] == 0) || (b.size == 1 && b.val[0] == 0))
{
c.size = 1;
c.val[0] = 0;
return c;
}
one.size = 1; //值為1的高精度整數(shù)
one.val[0] = 1;
high = a; //上界
low.size = 1; //下界
low.val[0] = 0;
while (ComPareBigInt(low, high) < 0)
{
mid = HalfBigInt(AddBigInt(high, low)); //中間數(shù)
c = MulBigInt(mid, b);
if (ComPareBigInt(c, a) == 0)
return mid;
else if (ComPareBigInt(c, a) < 0)
low = AddBigInt(mid, one);
else
high = SubBigInt(mid, one);
}
c = MulBigInt(low, b);
if (ComPareBigInt(c, a) <= 0)
return low;
else
return SubBigInt(low, one);
}
/*
函數(shù)名稱:HalfBigInt
函數(shù)功能:高精度整數(shù)求半
輸入?yún)?shù):BigInt a:用整型數(shù)組表示的高精度整數(shù)
輸出參數(shù):BigInt:返回用整型數(shù)組表示的高精度整數(shù)的一半
*/
BigInt HalfBigInt(BigInt a)
{
BigInt c;
c.size = a.size;
for (int i=a.size-1; i>0; i--)
{
c.val[i] = a.val[i] / 2;
if (a.val[i] % 2 == 1)
a.val[i-1] += WIDTHMAX;
}
c.val[0] = a.val[0] / 2;
if (c.size > 0 && c.val[c.size-1] == 0)
c.size--;
return c;
}