1. 程式人生 > >C++ 大數加、減、乘、除、乘方運算

C++ 大數加、減、乘、除、乘方運算

#include <iostream>
#include <string.h>
#include <time.h>
#define DIGIT	4
#define DEPTH	10000
#define MAX     100
#define MAXSIZE 200000
using namespace std;
typedef int bignum_t[MAX + 1];

/*
*Created by HarvestWu on 2018.06.28.
*/

//大數類
class  BigInteger
{
public:
	int read(bignum_t a, istream& is );//輸入資料
	void write(const bignum_t a, ostream& os );//輸出資料
	int comp(const bignum_t a, const int c, const int d, const bignum_t b);
	void add(bignum_t a, const bignum_t b);//大數加法
	void sub(bignum_t a, const bignum_t b);//大數減法
	void sub(bignum_t a, const bignum_t b, const int c, const int d);
	void mul(bignum_t c, const bignum_t a, const bignum_t b);//大數乘法
	void div(bignum_t c, bignum_t a, const bignum_t b);//大數除法
	void pow(int b, int n);//大數乘方
private:

};


//輸入資料
int BigInteger::read(bignum_t a, istream& is = cin)
{
	char buf[MAX*DIGIT + 1], ch;
	int i, j;
	memset((void*)a, 0, sizeof(bignum_t));
	if (!(is >> buf))	return 0;
	for (a[0] = strlen(buf), i = a[0] / 2 - 1; i >= 0; i--)
		ch = buf[i], buf[i] = buf[a[0] - 1 - i], buf[a[0] - 1 - i] = ch;
	for (a[0] = (a[0] + DIGIT - 1) / DIGIT, j = strlen(buf); j < a[0] * DIGIT; buf[j++] = '0');
	for (i = 1; i <= a[0]; i++)
	for (a[i] = 0, j = 0; j<DIGIT; j++)
		a[i] = a[i] * 10 + buf[i*DIGIT - 1 - j] - '0';
	for (; !a[a[0]] && a[0]>1; a[0]--);
	return 1;
}
//輸出資料
void BigInteger::write(const bignum_t a, ostream& os = cout)
{
	int i, j;
	for (os << a[i = a[0]], i--; i; i--)
	for (j = DEPTH / 10; j; j /= 10)
		os << a[i] / j % 10;
}

int BigInteger::comp(const bignum_t a, const int c, const int d, const bignum_t b)
{
	int i, t = 0, O = -DEPTH * 2;
	if (b[0] - a[0]<d&&c)
		return 1;
	for (i = b[0]; i>d; i--){
		t = t*DEPTH + a[i - d] * c - b[i];
		if (t > 0) return 1;
		if (t<O) return 0;
	}
	for (i = d; i; i--){
		t = t*DEPTH - b[i];
		if (t>0) return 1;
		if (t<O) return 0;
	}
	return t>0;
}

/*
*大數加法
*/
void BigInteger::add(bignum_t a, const bignum_t b)
{
	int i;
	for (i = 1; i <= b[0]; i++)
	if ((a[i] += b[i]) >= DEPTH)
		a[i] -= DEPTH, a[i + 1]++;
	if (b[0] >= a[0])
		a[0] = b[0];
	else
	for (; a[i] >= DEPTH&&i<a[0]; a[i] -= DEPTH, i++, a[i]++);
	a[0] += (a[a[0] + 1]>0);
}

/*
*大數減法
*/
void BigInteger::sub(bignum_t a, const bignum_t b)
{
	int i;
	for (i = 1; i <= b[0]; i++)
	if ((a[i] -= b[i]) < 0)
		a[i + 1]--, a[i] += DEPTH;
	for (; a[i]<0; a[i] += DEPTH, i++, a[i]--);
	for (; !a[a[0]] && a[0]>1; a[0]--);
}

void BigInteger::sub(bignum_t a, const bignum_t b, const int c, const int d)
{
	int i, O = b[0] + d;
	for (i = 1 + d; i <= O; i++)
	if ((a[i] -= b[i - d] * c) < 0)
		a[i + 1] += (a[i] - DEPTH + 1) / DEPTH, a[i] -= (a[i] - DEPTH + 1) / DEPTH*DEPTH;
	for (; a[i]<0; a[i + 1] += (a[i] - DEPTH + 1) / DEPTH, a[i] -= (a[i] - DEPTH + 1) / DEPTH*DEPTH, i++);
	for (; !a[a[0]] && a[0]>1; a[0]--);
}

/*
*大數乘法
*/
void BigInteger::mul(bignum_t c, const bignum_t a, const bignum_t b)
{
	int i, j;
	memset((void*)c, 0, sizeof(bignum_t));
	for (c[0] = a[0] + b[0] - 1, i = 1; i <= a[0]; i++)
	for (j = 1; j <= b[0]; j++)
	if ((c[i + j - 1] += a[i] * b[j]) >= DEPTH)
		c[i + j] += c[i + j - 1] / DEPTH, c[i + j - 1] %= DEPTH;
	for (c[0] += (c[c[0] + 1] > 0); !c[c[0]] && c[0] > 1; c[0]--);
}

/*
*大數除法
*/
void BigInteger::div(bignum_t c, bignum_t a, const bignum_t b)
{
	int h, l, m, i;
	memset((void*)c, 0, sizeof(bignum_t));
	c[0] = (b[0]<a[0] + 1) ? (a[0] - b[0] + 2) : 1;
	for (i = c[0]; i; sub(a, b, c[i] = m, i - 1), i--)
	for (h = DEPTH - 1, l = 0, m = (h + l + 1) >> 1; h>l; m = (h + l + 1) >> 1)
	if (comp(b, m, i - 1, a)) h = m - 1;
	else l = m;
	for (; !c[c[0]] && c[0] > 1; c[0]--);
	c[0] = c[0] > 1 ? c[0] : 1;
}

/*
*大數乘方
*/
void BigInteger::pow(int b, int n)
{
	time_t start, end;//計時
	int *a, i, j;
	start = time(NULL);
	a = (int *)malloc(sizeof(int)* MAXSIZE);
	for (i = 0; i<MAXSIZE; i++)
		a[i] = 0;
	a[MAXSIZE-1] = 1;
	for (i = 1; i<n + 1; i++)
	{
		for (j = 0; j<MAXSIZE; j++)

			a[j] *= b;
		for (j = MAXSIZE-1; j >= 0; j--)
		if (a[j] >= 10)
		{
			a[j - 1] += a[j] / 10;
			a[j] %= 10;
		}
	}
	end = time(NULL);
	for (i = 0; a[i] == 0; i++);
	for (i; i<MAXSIZE; i++)
		cout<<a[i];
	cout << endl;
	free(a);
	cout << "運算耗時:" << difftime(end, start) <<"ms"<< endl;

}

//運算選擇
void select(int s)
{
	bignum_t a, b, c;//儲存運算值
	time_t start, end;//計時
	BigInteger big;
	switch (s){
		case 1: 
			cout << "————下面將進行大數加法運算————" << endl;
			cout << "請輸入大數\na=";
			big.read(a);
			cout << "b=";
			big.read(b);
			cout << "運算結果:"; big.write(a); cout << "+"; big.write(b); cout << "=";
			start = time(NULL); big.add(a, b); end = time(NULL);
			big.write(a); cout << endl;
			cout << "運算耗時:" << difftime(end, start) << "ms" << endl;
			break;
		case 2: 
			cout << "————下面將進行大數減法運算————" << endl;
			cout << "請輸入大數\na=";
			big.read(a);
			cout << "b=";
			big.read(b);
			cout << "運算結果:"; big.write(a); cout << "-"; big.write(b); cout << "=";
			start = time(NULL); big.sub(a, b); end = time(NULL);
			big.write(a); cout << endl;
			cout << "運算耗時:" << difftime(end, start) << "ms" << endl;
			break;
		case 3: 
			cout << "————下面將進行大數乘法法運算————" << endl;
			cout << "請輸入大數\na=";
			big.read(a);
			cout << "b=";
			big.read(b);
			cout << "運算結果:"; big.write(a); cout << "*"; big.write(b); cout << "=";
			start = time(NULL); big.mul(c, a, b); end = time(NULL);
			big.write(c); cout << endl;
			cout << "運算耗時:" << difftime(end, start) << "ms" << endl;
			break;
		case 4: 
			cout << "————下面將進行大數除法運算————" << endl;
			cout << "請輸入大數\na=";
			big.read(a);
			cout << "b=";
			big.read(b);
			cout << "運算結果:"; big.write(a); cout << "/"; big.write(b); cout << "=";
			start = time(NULL); big.div(c, a, b); end = time(NULL);
			big.write(c); cout << endl;
			cout << "運算耗時:" << difftime(end, start) << "ms" << endl;
			break;
		case 5:
			cout << "————下面將進行大數乘方運算————" << endl;
			cout << "請輸入大數\na=";
			int d; cin >> d;
			cout << "冪\nn=";
			int n; cin >> n;
			cout << "運算結果:"<<d<<"^"<<n<<"=";
			big.pow(d, n);
			break;
		default:
			cout << "輸入非法,請重新輸入!" << endl;
			break;
	}
}

//選單欄
void menu()
{
	cout << endl;
	cout << "————歡迎使用大數運算系統——————" << endl;
	cout << "|                                      |" << endl;
	cout << "|請選擇您將進行的大數運算              |" << endl;
	cout << "|  1.大數加法                          |" << endl;
	cout << "|  2.大數減法                          |" << endl;
	cout << "|  3.大數乘法                          |" << endl;
	cout << "|  4.大數除法                          |" << endl;
	cout << "|  5.大數乘方                          |" << endl;
	cout << "|  0.退出系統                          |" << endl;
	cout << " ———————————————————"  << endl;
}
int main()
{
	while (1)
	{
		menu();
		int s;
		cin >> s;
		if (!s)break;
		select(s);
	}
	return 0;
}