首页 > 其他分享 >高精度四则及GCD运算(二元均是高精度)

高精度四则及GCD运算(二元均是高精度)

时间:2023-04-26 22:14:48浏览次数:55  
标签:return GCD 高精度 int 四则 La BI num const

原代码出处, 转自HDAWN, 经过部分改写, 包装为结构体, 常数比较大.

测试

image
输出
image
大概实际操作
image

具体

支持四则运算及GCD运算, 重写了istream和ostream和比较运算符.
构造函数既可以long long, string, 也可以char[]


如果除法要求余数, a / b = c, a - b * c = res, 除了这样绕一圈, 也可以BI::div(被除数, 除数, 商或余数), 其中第三维为true, 第三维为false.


求余数实际就是取模操作.


缺点:

  1. 不支持负数, 负数就只能减法
  2. 注意长度, MaxLen限定长度, 若长度大了, 常数也非常大
  3. 判小于0, 就是判第一个char是否是'-', 即判x.num.front() == '-'
  4. 注意二分写法: BI l = "0", r("1" + string(40, '0'));
  5. 若"1343"这样的char*在参与运算时, 需要显式强制转换
// 不支持负数, 负数就减法; 注意长度; 判小于0, 即判x.num.front() == '-'
// 注意二分写法: BI l = "0", r("1" + string(40, '0'));
// 若"1343"这样的char*在参与运算时, 可能需要显式强制转换
const int MaxLen = 1000;
struct BI {
	string num;
	
	static string SBI(long long x) {
		string s;
		while (x) s += char(x % 10 + '0'), x /= 10;
		if (s.empty()) s = "0";
		reverse(s.begin(), s.end());
		return s;
	}
	BI() = default;
	BI(long long a) : BI(SBI(a)) {}
	BI(string B) { num = B; }
	BI(const char *s) {
		int len = strlen(s);
		for (int i = 0; i < len; ++i) num += s[i];
	}
	
	friend istream &operator>>(istream &is, BI &rhs) {
		is >> rhs.num;
		return is;
	}
	friend ostream &operator<<(ostream &os, const BI &rhs) {
		for (auto c : rhs.num) os << c;
		return os;
	}
	
	char &operator[](int idx) { return num[idx]; }
	char operator[](int idx) const { return num[idx]; }
	
	bool operator==(BI rhs) const { return num == rhs.num; }
	bool operator!=(BI rhs) const { return !(*this == rhs); }
	bool operator<(BI B) const {
		if (num.size() != B.num.size()) return num.size() < B.num.size();
		for (int i = 0; i < num.size(); ++i)
			if (num[i] != B[i]) return num[i] < B[i];
		return false;
	}
	bool operator>(BI rhs) { return rhs < *this; }
	bool operator<=(BI rhs) { return !(rhs < *this); }
	bool operator>=(BI rhs) const { return !(*this < rhs); }
	
	BI operator+(const BI &B) const {
		string ans;
		int na[MaxLen] = {0}, nb[MaxLen] = {0};
		int la = num.size(), lb = B.num.size(), lmax = max(la, lb);
		for (int i = 0; i < la; i++) na[la - 1 - i] = num[i] - '0';
		for (int i = 0; i < lb; i++) nb[lb - 1 - i] = B[i] - '0';
		for (int i = 0; i < lmax; i++) na[i] += nb[i], na[i + 1] += na[i] / 10, na[i] %= 10;
		if (na[lmax]) lmax++;
		for (int i = lmax - 1; i >= 0; i--) ans += char(na[i] + '0');
		return ans;
	}
	BI operator+(const long long B) const { return *this + SBI(B); };
	
	BI operator-(BI B) const {
		BI A = *this, C;
		if (*this < B) {
			C = B - *this;
			C.num = "-" + C.num;
			return C;
		}
		
		int la = A.num.size(), lb = B.num.size();
		reverse(A.num.begin(), A.num.end()),
		reverse(B.num.begin(), B.num.end());
		for (int i = 0, t = 0; i < la; i++) {
			t = (A[i] - '0') - t;
			if (i < lb) t -= B[i] - '0';
			C.num += char((t + 10) % 10 + '0');
			if (t < 0) t = 1;
			else t = 0;
		}
		
		while (C.num.size() > 1 && C.num.back() == '0') C.num.pop_back();
		reverse(C.num.begin(), C.num.end());
		return C;
	}
	BI operator-(const long long B) const { return *this - SBI(B); };
	
	static int sub(int *a, const int *b, int La, int Lb) {
		if (La < Lb) return -1;//如果a小于b,则返回-1
		if (La == Lb) {
			for (int i = La - 1; i >= 0; i--)
				if (a[i] > b[i]) break;
			else if (a[i] < b[i]) return -1;//如果a小于b,则返回-1
		}
		for (int i = 0; i < La; i++) {//高精度减法
			a[i] -= b[i];
			if (a[i] < 0) a[i] += 10, a[i + 1]--;
		}
		for (int i = La - 1; i >= 0; i--)
			if (a[i]) return i + 1;//返回差的位数
		return 0;//返回差的位数
	}
	
	BI operator*(const BI &B) const {
		string s;
		int na[MaxLen]{}, nb[MaxLen]{}, nc[MaxLen]{},
		La = num.size(), Lb = B.num.size();//na存储被乘数,nb存储乘数,nc存储积
		for (int i = La - 1; i >= 0; i--) na[La - i] = num[i] - '0';//将字符串表示的大整形数转成i整形数组表示的大整形数
		for (int i = Lb - 1; i >= 0; i--) nb[Lb - i] = B[i] - '0';
		for (int i = 1; i <= La; i++) {//a的第i位乘以b的第j位为积的第i+j-1位(先不考虑进位)
			for (int j = 1; j <= Lb; j++) nc[i + j - 1] += na[i] * nb[j];
		}
		for (int i = 1; i <= La + Lb; i++) nc[i + 1] += nc[i] / 10, nc[i] %= 10;//统一处理进位
		if (nc[La + Lb]) s += char(nc[La + Lb] + '0');//判断第i+j位上的数字是不是0
		for (int i = La + Lb - 1; i >= 1; i--) s += char(nc[i] + '0');//将整形数组转成字符串
		return s;
	}
	BI operator*(const long long B) const { return *this * SBI(B); };
	
	static BI div(BI n1, BI n2, bool fl) {// true返回商, false余数
		string s, v;// s存商,v存余数
		int a[MaxLen]{}, b[MaxLen]{}, r[MaxLen]{},
		La = n1.num.size(), Lb = n2.num.size(), tp = La;
		//a,b是整形数组表示被除数,除数,tp保存被除数的长度
		for (int i = La - 1; i >= 0; i--) a[La - 1 - i] = n1[i] - '0';
		for (int i = Lb - 1; i >= 0; i--) b[Lb - 1 - i] = n2[i] - '0';
		//如果a<b,则商为0,余数为被除数
		if (La < Lb || (La == Lb && n1 < n2)) return (fl ? "0" : n1);
		int t = La - Lb;//除被数和除数的位数之差
		for (int i = La - 1; i >= 0; i--)//将除数扩大10^t倍
			if (i >= t) b[i] = b[i - t];
		else b[i] = 0;
		Lb = La;
		for (int i = 0; i <= t; i++) {
			int temp;//如果被除数比除数大继续减
			while ((temp = sub(a, b + i, La, Lb - i)) >= 0) {
				La = temp;
				r[t - i]++;
			}
		}
		int p;
		for (p = 0; p < MaxLen - 10; p++) r[p + 1] += r[p] / 10, r[p] %= 10;//统一处理进位
		while (!r[p]) p--;//将整形数组表示的商转化成字符串表示的
		while (p >= 0) s += char(r[p--] + '0');
		p = tp;
		while (!a[p]) p--;//将整形数组表示的余数转化成字符串表示的</span>
		while (p >= 0) v += char(a[p--] + '0');
		if (v.empty()) v = "0";
		return (fl ? s : v);
	}
	BI operator/(BI n2) const { return div(*this, n2, true); }
	BI operator/(const long long B) const { return *this / SBI(B); };
	
	static bool jud(const string &s) {//判断s是否为全0串
		for (char i : s) if (i != '0') return false;
		return true;
	}
	
	static BI gcd(BI a, BI b) {
		BI t;//如果余数不为0,继续除
		while (!jud(b.num)) {
			t = a;//保存被除数的值
			a = b;//用除数替换被除数
			b = div(t, b, false);//用余数替换除数
		}
		return a;
	}
};
BI gcd(BI &A, BI &B) { return BI::gcd(A, B); }
// 不支持负数, 负数就减法; 注意长度; 判小于0, 即判x.num.front() == '-'
// 注意二分写法: BI l = "0", r("1" + string(40, '0'));
// 若"1343"这样的char*在参与运算时, 可能需要显式强制转换

例题

  1. https://codeforces.com/gym/103373/problem/E
  2. https://codeforces.com/gym/102028/problem/E

标签:return,GCD,高精度,int,四则,La,BI,num,const
From: https://www.cnblogs.com/LiamEvander/p/17357498.html

相关文章

  • 高精度模板 大数减大数 可变数组vector实现
    vector<int>Sub(vector<int>&A,vector<int>&B)//这里默认长数减去短数{vector<int>C;//结果向量intT=0;//上一位借位标志位for(inti=0;i<A.size();i++){T=A[i]-T;if(i<B.size())T-=B[i];//检......
  • 高精度模板 整数大数除以小整数数
    vector<int>Div(vector<int>&A,int&B){vector<int>C;intT=0;//除数for(inti=A.size()-1;i>=0;i--)//注意,除法模拟是从最高位开始的{T=T*10+A[i];//更新除数C.push_back(T/B);T%=B;......
  • c如何输出高精度浮点型数
    环境:cygwin64的gcc (mingw64的gcc不行)intmain(intargc,charconst*argv[]){longdoubleld=1.23L;printf("1%Lf\n",ld);doubled=1.3456789123;printf("2%f\n",d);printf("3%lf\n",d);printf("4%ll......
  • gcd(a+c,b+c)!=1,求最小的c
    https://ac.nowcoder.com/acm/contest/54877/E根据更相减损法gcd(a+c,b+c)=gcd(a-b,a+c),由于a,b已经给出,a-b为固定值。当a-b为1时,无解当a-b为0时,若a=1,则c=1,否则c=0对于a-b=其他,对a-b做质因子分解,对于每一个质因子d去求最小的c使得gcd(d,a+c)!=1,发现c=d-a%d,......
  • Java中处理高精度数据计算
    1、为什么要使用高精度计算拿整数举例:在Java中,int和long是两种基本数据类型,而BigInteger是一个对象类型。它们的取值范围如下:-int:32位有符号整数,取值范围为-2^31~2^31-1(即-2147483648~2147483647)。-long:64位有符号整数,取值范围为-2^63~2^63-1(即-9223......
  • w2-4 高精度减法
    #include<iostream>#include<string>usingnamespacestd;intsum[50000];intmain(){stringa,b;longlongx,y;cin>>a>>b;intjug=0,pd=0;if((a<b&&a.size()==b.size())||a.size()<b.siz......
  • 结对编程——随机生成四则运算程序
    在本次结对编程中,我和2152634王锴中同学一同进行参与了随机生成四则运算题目程序的编写,本次编写环境在clion上,使用c++风格的代码完成编写。在编写的过程中,我们一同探讨了用哪种语言进行编译,最终选定c++,原因在于对c++的掌握程度更深。在一起完成此项目的同时,我们收获了很多,尤其对方......
  • 结对编程——300道小学四则运算
    本次结对编程作业由我和2152620同学使用c++语言共同完成。代码如下:#include<iomanip>#include<iostream>#include<ctime>#include<cstdlib>usingnamespacestd;intnum1[300];intnum2[300];intop[300];intanswer[300];intreal[300];voidsrand(unsigne......
  • 高精度加法、减法、乘法【自存】
    预处理intMax_len;//最多可能的位数stringa,b;voidinit(){cin>>a>>b;Max_len=500;//intind=Max_len,i=a.size()-1;while(i>=0){ans[ind]=a[i]-'0';ind--;i--;}in......
  • 在有限 computational budget 下,借助 low-fidelity 模型提高精度
    论文名称:context-awarelearningofhierarchiesoflow-fidelitymodelsformulti-fidelityuncertaintyquantification链接:https://www.sciencedirect.com/science/article/pii/S0045782523000312国际计算力学领域的顶级期刊《ComputerMethodsinAppliedMechanicsand......