高精度算法(加减乘除取模(均可以处理负数))

前言

不得不说csdn上面的文章是越来越乱了,搞的想骂人的那种。本文在这里声明,这是一篇模板的博客,如果向更深入的了解(会提及一些)可以去参考别的文章。没一个模板都经过博主简化和模块化已达到易写的目的。

大数加法

不可以处理负数的模板

// C = A + B, A >= 0, B >= 0
vector<int> add(vector<int> &A, vector<int> &B)
{
    if (A.size() < B.size()) return add(B, A);

    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);
    return C;
}

可以处理负数

因为减法就是带负数的加法,因此我们在处理负数的时候一般是对负数的情况进行讨论

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
char a[1000005];
char b[1000005];
int fa, fb;
int la, lb;

void show(int ed) {
	if (fa)
		printf("-");
	for (int i = ed; i >= fa; --i)
		printf("%d", a[i]);
}

// 两个都为负数或者两个都不是负数的情况
void add() {
	int i, j, t = 0, s, l;
	for (i = fa; i < la || i < lb; ++i) {
		s = a[i]  + b[i]   + t;
		t = s / 10;
		a[i] = s % 10;
	}
	a[i] = t ;
	l = t ? i : i - 1;//t是进位 ,如果最后进位了,这l为i,否则只到i-1
	show(l);
}

//比较大小
int cmp() {
	int la = strlen(a), lb = strlen(b);
	if (la - fa > lb - fb) // 比较长度
		return 1;
	else if (la - fa < lb - fb)
		return 0;
	else {
		// 长度相等则看每一位
		int i ;
		for ( i = 0; i < la && a[i + fa] == b[i + fb]; ++i);
		return a[i + fa] > b[i + fb];
	}
}

void minu() {
	//两个符号不一样的话是利用减法
	int i, j, c = 0, l = -1, s;
	for (i = 0; i + fa < la; ++i) {
		s = a[i + fa] - b[i + fb] - c >= 0 ? 0 : 1; //是否需要借位
		a[i + fa] = (10 + a[i + fa] - b[i + fb] - c) % 10;
		l = a[i + fa] ? i + fa : l; //判断末尾位置
		c = s;
	}
	if (l < 0)
		printf("0");
	else
		show(l);
}

int main() {
	scanf("%s%s", a, b);
	fa = ('-' == a[0]), fb = ('-' == b[0]);
	// 我们早两者如果只有一个负数的时候,我们让前一个数大的原因是这样我们就可以通过前一个确实整个的符号
	if ( !cmp())
		swap(a, b), swap(fa, fb);
	la = strlen(a), lb = strlen(b);
	reverse(a + fa, a + la), reverse(b + fb, b + lb); // 易忘
	int i = fa, j = fb;
	while (i < la)
		a[i] -= '0', i ++;
	while (j < lb)
		b[j] -= '0', j ++;//j容易写成i
	if (fa ^ fb)
		minu(); // 两个只有有一个有负号 ,减法
	else
		add(); // 加法
	return 0;
}

大数减法

两个数都是整数,且相减结果大于0

// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> &A, vector<int> &B)
{
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;
        else t = 0;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

两个数都是正整数,相减结果可以是负数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
char a[1000005];
char b[1000005];
int la, lb;

//比较大小
int cmp() {
	int la = strlen(a), lb = strlen(b);
	if (la  > lb ) // 比较长度
		return 1;
	else if (la  < lb )
		return 0;
	else {
		// 长度相等则看每一位
		int i  = 0;
		while (i < la && a[i] == b[i])
			i ++;
		return a[i] >  b[i];
	}
}

void minu() {
	int i, j, t = 0, ed = -1;
	for (i = 0; i < la || i < lb; ++i) {
		int s = a[i] - b[i] - t >= 0 ? 0 : 1; //是否需要借位
		a[i] = (10 + a[i] - b[i] - t) % 10;
		ed = a[i] ? i  : ed; //判断末尾位置
		t = s;
	}
	if (ed < 0)
		printf("0");
	else
		for (int i = ed ; i >= 0 ; --i)
			printf("%d", a[i]);
}

int main() {
	scanf("%s%s", a, b);
	// 我们早两者如果只有一个负数的时候,我们让前一个数大的原因是这样我们就可以通过前一个确实整个的符号
	if ( !cmp()) {
		cout << '-';
		swap(a, b);
	}
	la = strlen(a), lb = strlen(b);
	reverse(a, a + la), reverse(b, b + lb);   // 易忘
	int i = 0, j = 0;
	while (i < la)
		a[i] -= '0', i ++;
	while (j < lb)
		b[j] -= '0', j ++;//j容易写成i
	minu();
	return 0;
}

两个数均可以是负数

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string a, b, s, t;
int fa, fb;

void init() {
	fa = (a[0] == '-'), fb = (b[0] == '-');
	s = a.substr( 1, a.size() ), t = b.substr( 1, b.size() );
}

bool cmp(string a, string b) {
	int as = a.size(), bs = b.size();
	if (as > bs || as == bs && a > b)
		return true;
	else
		return false;
}

void change(string &s, string &t, string a, string b) {
	int as = a.size(), bs = b.size(), d = as > bs ? as - bs : bs - as;
	for ( int i = 0; i < d; i++ )
		as > bs ? t += "0" : s += "0";
	s += a, t += b; // 前边补上0
}

string calcAddition( string a, string b ) {
	string s = "0", t = "0";//多放的一个0是加法可能会进一位
	change(s, t, a, b);
	int len = s.size();
	for ( int i = len - 1; i >= 1; i-- )
		s[i] += t[i] - '0';
	if ( s[i] > '9' ) {
		s[i] -= 10;
		s[i - 1]++;
	}
	bool j = true;
	for ( int i = 0; i < len; i++ )
		if ( s[i] != '0' )
			j = false;
	if ( j )
		return "0";
	return s[0] == '0' ? s.substr( 1, len ) : s;
}

string calcSubtraction( string a, string b ) {
	string s = "", t = "";
	change(s, t, a, b);
	if ( s < t )
		swap(s, t);
	int len = s.size();
	for ( int i = len - 1; i >= 0; i-- ) {
		if ( s[i] < t[i] ) {
			s[i] += 10;
			if ( s[i - 1] >= '1' )
				s[i - 1]--;
			else { // 否则向前边不是0的借位
				int j = i - 1;
				while ( s[j] == '0' )
					s[j--] += 9;//
				s[j]--;
			}
		}
		s[i] -= ( t[i] - '0' );
	}
	if ( len == 1 )
		return s;
	return s[0] == '0' ? calcAddition( s.substr( 1, len ), "0" ) : s;
}

int main() {
	cin >> a >> b;
	init();
	if ( fa && fb ) {
		if ( cmp(s, t) )
			cout << "-";
		cout << calcSubtraction( s, t ) << endl;
	} else if ( !fa && !fb ) {
		if (!cmp(a, b) )
			cout << "-";
		cout << calcSubtraction( a, b ) << endl;
	} else if ( fa )
		cout << "-" << calcAddition( s, b ) << endl;
	else
		cout << calcAddition( a, t ) << endl;

	return 0;
}


高精度乘法

一个结论是:两个相乘的数,第一个数的第i为与第二个数的第j位(从1开始),相乘的结果是累加到第 结果的第i + j - 1位上的。

两个数均可以是负数

#include <iostream>
#include <cstring>
#define T 1000000
using namespace std;
char a1[T], b1[T];
int a[T], b[T], c[T], lena, lenb, lenc, x, t, f;

void mul() {
	for (int i = 1; i <= lena; i++) {
		x = 0;//x是进位
		for (int j = 1; j <= lenb; j++) {
			c[i + j - 1] += a[i] * b[j] + x ;
			x = c[i + j - 1] / 10;
			c[i + j - 1] %= 10;
		}
		c[i + lenb] = x;
	}
	lenc = lena + lenb;
	while (c[lenc] == 0 && lenc > 1)
		lenc--;
	if (f == -1)
		cout << "-";
	for (int i = lenc; i >= 1; i--)
		cout << c[i];
	cout << endl;
}

int main() {
	cin >> a1 >> b1 ;
	lena = strlen(a1), lenb = strlen(b1);
	f = 1, t = 0;
	if (a1[0] == '-')  //判断第一个字符是不是负数,如果是,再判断另一个是不是,再想输出问题对于B1字符数组同理
		f *= -1, t++;
	for (int i = t; i <= lena - 1; i++)
		a[lena - i] = a1[i] - '0'; //除去符号位后,将字符变成数字,放在对应的int数组里面,进行计算
	t = 0;
	if (b1[0] == '-')
		f *= -1, t++;
	for (int i = t; i <= lenb - 1; i++)
		b[lenb - i] = b1[i] - '0';
	mul();
	return 0;
}

大数除法

两个数均可以是负数

#include <iostream>
#include <string>
using namespace std;

string fixedNum( string a ) {
	if ( a.size() == 1 )
		return a;
	for ( int i = 0; i < a.size(); i++ )
		if ( '1' <= a[i] && a[i] <= '9' )
			return a.substr( i, a.size() );
	return "0";
}

string calcAddition( string a, string b ) {
	a = fixedNum(a);
	b = fixedNum(b);
	int as = a.size(), bs = b.size(), d = as > bs ? as - bs : bs - as;
	string s = "0", t = "0";
	for ( int i = 0; i < d; i++ )
		as > bs ? t += "0" : s += "0";
	s += a;
	t += b;

	for ( int i = s.size() - 1; i >= 1; i-- ) {
		s[i] += t[i] - '0';
		if ( s[i] > '9' ) {
			s[i] -= 10;
			s[i - 1]++;
		}
	}
	return s[0] == '0' ? s.substr( 1, s.size() ) : s;
}

string calcSubtraction( string a, string b ) {
	int as = a.size(), bs = b.size(), d = as - bs;
	string s = "", t = "";
	for ( int i = 0; i < d; i++ )
		t += "0";

	s += a;
	t += b;

	for ( int i = s.size() - 1; i >= 0; i-- ) {
		if ( s[i] < t[i] ) {
			s[i] += 10;
			if ( s[i - 1] >= '1' )
				s[i - 1]--;
			else {
				int j = i - 1;
				while ( s[j] == '0' )
					s[j--] += 9;
				s[j]--;
			}
		}
		s[i] -= ( t[i] - '0' );
	}

	if ( s.size() == 1 )
		return s;

	for ( int i = 0; i < s.size(); i++ ) {
		if ( '1' <= s[i] && s[i] <= '9' )
			return s.substr( i, s.size() );
	}
	return "0";
}

int main() {
	string a, b, c, sum = "0", cnt = "1";
	bool j1 = false;
	cin >> a >> b;

	if ( a == "0" ) {
		cout << 0 << endl;
		return 0;
	} else if ( a[0] == '-' && b[0] == '-' ) {
		a = a.substr( 1, a.size() );
		b = b.substr( 1, b.size() );
	} else if ( a[0] == '-' ) {
		j1 = true;
		a = a.substr( 1, a.size() );
	} else if ( b[0] == '-' ) {
		j1 = true;
		b = b.substr( 1, b.size() );
	} else;

	c = b;
	int as = a.size(), bs = b.size(), cs, d = as - bs;
	for ( int i = 0; i < d - 1; i++ ) {
		c += "0";
		cnt += "0";
	}
	cs = c.size();

	bool j2 = false;
	while ( c != b ) {
		while ( as > cs || as == cs && a >= c ) {
			j2 = true;
			a = calcSubtraction( a, c );
			as = a.size();
			sum = calcAddition( sum, cnt );
		}
		c = c.substr( 0, c.size() - 1 );
		cnt = cnt.substr( 0, cnt.size() - 1 );
		cs = c.size();
	}

	while ( as > bs || as == bs && a >= b ) {
		j2 = true;
		a = calcSubtraction( a, b );
		sum = calcAddition( sum, cnt );
		as = a.size();
	}

	if ( j1 && j2 )
		cout << '-';
	cout << sum << endl;

	return 0;
}


大数取模

#include <iostream>
#include <string>
using namespace std;

string calcAddition( string a, string b ) {
	int as = a.size(), bs = b.size(), d = as > bs ? as - bs : bs - as;
	string s = "0", t = "0";
	for ( int i = 0; i < d; i++ )
		as > bs ? t += "0" : s += "0";
	s += a;
	t += b;

	for ( int i = s.size() - 1; i >= 1; i-- ) {
		s[i] += t[i] - '0';
		if ( s[i] > '9' ) {
			s[i] -= 10;
			s[i - 1]++;
		}
	}

	bool j = true;
	for ( int i = 0; i < s.size(); i++ )
		if ( s[i] != '0' )
			j = false;
	if ( j )
		return "0";
	return s[0] == '0' ? s.substr( 1, s.size() ) : s;
}

string calcSubtraction( string a, string b ) {
	int as = a.size(), bs = b.size(), d = as - bs;
	string s = "", t = "";
	for ( int i = 0; i < d; i++ )
		t += "0";

	s += a;
	t += b;

	for ( int i = s.size() - 1; i >= 0; i-- ) {
		if ( s[i] < t[i] ) {
			s[i] += 10;
			if ( s[i - 1] >= '1' )
				s[i - 1]--;
			else {
				int j = i - 1;
				while ( s[j] == '0' )
					s[j--] += 9;
				s[j]--;
			}
		}
		s[i] -= ( t[i] - '0' );
	}

	if ( s.size() == 1 )
		return s;

	for ( int i = 0; i < s.size(); i++ ) {
		if ( '1' <= s[i] && s[i] <= '9' )
			return s.substr( i, s.size() );
	}

	return "0";
}

int main() {
	string a, b, c;

	cin >> a >> b;

	c = b;
	int as = a.size(), bs = b.size(), cs, d = as - bs;
	for ( int i = 0; i < d - 1; i++ )
		c += "0";
	cs = c.size();

	while ( c != b ) {
		while ( as > cs || as == cs && a >= c ) {
			a = calcSubtraction( a, c );
			as = a.size();
		}
		c = c.substr( 0, c.size() - 1 );
		cs = c.size();
	}

	while ( as > bs || as == bs && a >= b ) {
		a = calcSubtraction( a, b );
		as = a.size();
	}

	cout << a << endl;


	return 0;
}


  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落春只在无意间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值