学习面向对象编程 - 创建一个高精度类

/*
High Accuracy Calculator

*** To name a new number, you may write like this: num a. Then it'll create a 0 in Decimalism
*** But it's also OK to write like this: num a(string, int , int ).
*** The second argument stands for the number system, and the third one represents the plus or minus.

---------------------
--vecsion 0.1	2022/11/6
*** Notice that 'this' represents the number you dedicate.
*** struct ntoc renamed to class Digit_Charactor_Tranformation and its member is protected now.

This version fixes some bugs include:
	1.negative integers' addition (function name: ad)  and subtarcttion (function name: mi).
	2.numbers' comparation(function name: cmp_with,max_with,min_with), 
	  addition and substaction in different number system.

The version include the calculation functions below:
	0.example: function - function name(target type) - return type - return value
	1.addition - ad(num) - num - the sum
	2.minus - mi(num) - num - the difference ('this' - 'target')
	3.multiple (only Decimalism and to small numbers) - mul(int) - num - the product
	4.division (only Decimalism and to small numbers) - dv(int) - num - the quotient ('this' / 'target')
	5.modulo (only Decimalism and to small numbers) - mod(int) - int - the remainder ('this' % 'target')
	6.division with remainder (only Decimalism and to small numbers) - dv_with_rem(int) - pair<num,int> - /
	7.compare - cmp_with(num) - bool - If 'this' < 'target', return true. 'flase' otherwise.
	8.maximum - max_with(num) - num - return the bigger one.
	9.minimum - min_with(num) - num return the smaller one.

And here're some assistant functions (All of them return nothing, just void):
	1.num_clear(void) is to clean a number;
	2.update(string,int,int) is to overwrite 'this' with the dedicated number and system.
	3.print(void) is to print 'this'.
	
---------------------
--vecsion 0.2	2022/11/6

This version fixes only one bug :
	The problem of 0 and prefix 0.

This version adds functions below :
	1.multiple (any number system) - hmul(num) - num - the product
	2.division (any number system) - hdiv(num) - num - the quotient
	3.modulo (any number system) - hmod(num) - num- the remainder
	4.check if it's 0 - is_0(num) - bool - Returning true if it's 0. Otherwise, 1.

---------------------
--vecsion 0.3	2022/11/7

This version fixed whis bug:
	A number times 0.

The version adds functions below:
	1.high accuracy number's transformation to an integer in Dec - into_integer(void) - int
	*** WARNING *** 
		It can only contain a small integer. When it comes to a large number, it
		will ignore the high digits.
	
	2.high accuracy number's transformation to an integer in Dec - into_long_long_integer(void) - long long
	*** WARNING *** 
		It can only contain a small integer in type 'long long int'. When it comes to a large number, it
		will ignore the high digits.
	
	3.Quick power - Pow_Q(int) - num - the involution
		Notice that its speed's not fast actually.
	
And here comes a new function ------- returning value! It can remind you the reason of the error.
	1. If it returns '114514', you have exactly performed a wrong input.
	2. If it returns '1919810', you porbably have performed the operations below:
		A. At least one divisor is 0.
		B. At least one modulor(?) is 0.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
class Digit_Charactor_Tranformation{
	protected:
		char ch[62];
		Digit_Charactor_Tranformation(void){
			for(char i='0';i<='9';i++)ch[i-'0']=i;
			for(char i='A';i<='Z';i++)ch[i-'A'+10]=i;
			for(char i='a';i<='z';i++)ch[i-'a'+36]=i;
		}
		int c2n(char n){
			if(isdigit(n))return n-'0';
			if(isupper(n))return n-'A'+10;
			if(islower(n))return n-'a'+36;
			return -1;
		}
	public:
		string n2s(int n){
			string tar="";
			bool flag=false;
			if(n<0) flag=true;
			while(n){
				tar+=char(n%10+'0');
				n/=10;
			} 
			if(flag) tar+='-';
			reverse(tar.begin(),tar.end());
			return tar;
		}
};
class num:public Digit_Charactor_Tranformation{
	vector<int>bit;	//Actually it means digit
	int basenum;
	//default to Decimalism
	int minu;
	//1 means it's positive. If -1, it's negetive.
	void delete_0(){ 
		while(bit.size()>0&&bit.back()==0)
			bit.pop_back();
	}
	protected:
		num mul(num tar){
			num ans("",basenum,minu*tar.minu),carry;
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			int ls=bit.size();
			for(int i=0;i<ls||!carry.is_0();i++){
				if(i<ls) carry=carry.ad(tar.mul(bit[i]));
				ans.bit.push_back(carry.mod(basenum));
				carry=carry.dv(basenum);
			} ans.delete_0();
			return ans;
		}
		num dv(num tar){
			if(tar.is_0()){
				puts("Math Error. No Result.");
				exit(1919810);
			}
			num ans("",basenum,minu*tar.minu),remain,prd;
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			int ls=bit.size()-1,quotient;
			for(int i=ls;i>=0;i--){
				remain=remain.mul(basenum).ad(num(n2s(bit[i]),basenum));
				if(remain.cmp_with(tar)){
					ans.bit.push_back(0);
					continue;
				}quotient=0;prd=tar;
				while(prd.cmp_with(remain)||prd.equals_to(remain)) prd=prd.ad(tar),++quotient;
				ans.bit.push_back(quotient);
				remain=remain.mi(prd.mi(tar));
			} reverse(ans.bit.begin(),ans.bit.end());
			ans.delete_0();
			return ans;
		}
		num mod(num tar){
			if(tar.is_0()){
				puts("Math Error. No Result.");
				exit(1919810);
			}
			num remain,prd;
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			int ls=bit.size()-1;
			for(int i=ls;i>=0;i--){
				remain=remain.mul(basenum).ad(num(n2s(bit[i]),basenum));
				if(remain.cmp_with(tar))continue;
				prd=tar;
				while(prd.cmp_with(remain)||prd.equals_to(remain)) prd=prd.ad(tar);
				remain=remain.mi(prd.mi(tar));
			}
			return remain;
		}
		num Pow(int tar){
			if(tar==0)return num("1",basenum,minu);
			if(tar==1)return (*this);
			num ans=(*this).Pow(tar>>1);
			if(tar&1) return ans.mul(ans).mul(*this);
			return ans.mul(ans);
		}
		bool is_0(){return (bit.size()==0);}
		num mul(int tar){
			num ans("",basenum,minu*(tar==0?1:tar/abs(tar)));
			int ls=bit.size(),carry=0;
			for(int i=0;i<ls||carry;i++){
				if(i<ls)carry+=bit[i]*tar;
				ans.bit.push_back(carry%basenum);
				carry/=basenum;
			} ans.delete_0();
			return ans;
		}
		num dv(int tar){
			if(tar==0){
				puts("Math Error. No Result.");
				exit(1919810);
			}
			num ans("",basenum,minu*tar/abs(tar));
			int ls=bit.size()-1,remain=0;
			for(int i=ls;i>=0;i--){
				remain=remain*basenum+bit[i];
				ans.bit.push_back(remain/tar);
				remain%=tar;
			} reverse(ans.bit.begin(),ans.bit.end());
			ans.delete_0();
			return ans;
		}
		num mi(num tar){
			num ans("",basenum);
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(minu<0){
				tar.minu*=-1;
				return tar.ad((*this));
			}else if(tar.minu<0) return tar.mi((*this));
			if(this->cmp_with(tar)){
				ans=tar.mi(*this);
				ans.minu*=-1;
				return ans;
			} 
			int remain=0;
			for(int i=0;i<int(bit.size());i++){
				remain=bit[i]-remain;
				if(i<int(tar.bit.size()))remain-=tar.bit[i];
				ans.bit.push_back((remain+basenum)%basenum);
				if(remain<0)remain=1;
				else remain=0;
			} ans.delete_0();
			return ans;
		} 
		num mi(int target){
			num ans("",basenum),tar(n2s(target));
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(minu<0){
				tar.minu*=-1;
				return tar.ad((*this));
			}else if(tar.minu<0) return tar.mi((*this));
			if(this->cmp_with(tar)){
				ans=tar.mi(*this);
				ans.minu*=-1;
				return ans;
			} 
			int remain=0;
			for(int i=0;i<int(bit.size());i++){
				remain=bit[i]-remain;
				if(i<int(tar.bit.size()))remain-=tar.bit[i];
				ans.bit.push_back((remain+basenum)%basenum);
				if(remain<0)remain=1;
				else remain=0;
			} ans.delete_0();
			return ans;
		} 
		num ad(num tar) {
			num ans("",basenum,minu);
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			//check the symbol
			if(minu<0){
				if(tar.minu<0) ans.minu=-1;
				else return tar.mi((*this));
			}else if(tar.minu<0){tar.minu=1;return (*this).mi(tar);}
			int remain=0,ls=bit.size(),lt=tar.bit.size();
			for(int i=0;i<ls||i<lt;i++){
				if(i<ls)remain+=bit[i];
				if(i<lt)remain+=tar.bit[i];
				ans.bit.push_back(remain%basenum);
				remain/=basenum;
			}
			if(remain) ans.bit.push_back(1);
			ans.delete_0();
			return ans;
		}
		num ad(int target) {
			num ans("",basenum,minu),tar(n2s(target));
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			//check the symbol
			if(minu<0){
				if(tar.minu<0) ans.minu=-1;
				else return tar.mi((*this));
			}else if(tar.minu<0){tar.minu=1;return (*this).mi(tar);}
			int remain=0,ls=bit.size(),lt=tar.bit.size();
			for(int i=0;i<ls||i<lt;i++){
				if(i<ls)remain+=bit[i];
				if(i<lt)remain+=tar.bit[i];
				ans.bit.push_back(remain%basenum);
				remain/=basenum;
			}
			if(remain) ans.bit.push_back(1);
			ans.delete_0();
			return ans;
		}
		int mod(int tar){
			if(tar==0){
				puts("Math Error. No Result.");
				exit(1919810);
			}
			int ls=bit.size()-1,remain=0;
			for(int i=ls;i>=0;i--){
				remain=remain*basenum+bit[i];
				remain%=tar;
			}return minu*remain;
		}
	
	public:
		num(string source="",int basen=10,int minuss=1):basenum(basen),minu(minuss){
			if(basenum<=1){
				puts("System Error - Basenum's Too Small");
				exit(1919810);
			}
			if(source=="") {bit.clear();return;}
			for(int i=source.size()-1;i>0;i--){
				if(c2n(source[i])==-1){
					puts("System Error - Illegal Input");
					exit(114514);
				}bit.push_back(c2n(source[i]));
			}
			if(source[0]=='-')minu*=-1;
			else if(c2n(source[0])>=0)bit.push_back(c2n(source[0]));
			else {
				puts("System Error - Illegal Input");
				exit(114514);
			}
			delete_0();
		}
		void num_clear(){
			bit.clear();
			basenum=10,minu=1;
			delete_0();
		}
		void update(string source,int basen=10,int m=1){
			basenum=basen,minu=m;
			bit.clear();
			if(source=="") return ;
			for(int i=source.size()-1;i>0;i--)
				bit.push_back(c2n(source[i]));
			if(source[0]=='-')minu*=-1;
			else bit.push_back(c2n(source[0]));
			delete_0();
		}
		void update(int source,int basen=10,int m=1){
			basenum=basen,minu=m;
			bit.clear();
			if(source==0) return ;
			minu*=abs(source)/source;
			source=abs(source);
			while(source){
				bit.push_back(source%basen);
				source/=basen;
			}delete_0();
		}
		void get(){
			string str;
			cin>>str;
			update(str);
		}
		int into_integer(){
			int ans=0,i=0;
			while(int(bit[i]*pow(basenum,i))>0&&
			ans+int(bit[i]*pow(basenum,i))>0)
				ans+=bit[i++]*pow(basenum,i);
			return ans*minu;
		}
		long long into_long_long_integer(){
			long long ans=0ll,i=0;
			while((long long)(1ll*bit[i]*pow(basenum,i))>0ll&&
			ans+(long long)(1ll*bit[i]*pow(basenum,i))>0)
				ans+=(long long)(1ll*bit[i]*pow(basenum,i));
			return ans*minu;
		}
		
		num max_with(num tar){//return the bigger one
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(bit.size()!=tar.bit.size())
				return bit.size()<tar.bit.size()?tar:(*this);
			else for(int i=bit.size()-1;i>=0;i--){
				if(bit[i]!=tar.bit[i])
					return bit[i]<tar.bit[i]?tar:(*this);	
			}return tar;
		}
		num min_with(num tar){//return the smaller one
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(bit.size()!=tar.bit.size())
				return bit.size()<tar.bit.size()?(*this):tar;
			else for(int i=bit.size()-1;i>=0;i--){
				if(bit[i]!=tar.bit[i])
					return bit[i]<tar.bit[i]?(*this):tar;	
			}return tar;
		}
		bool cmp_with(num tar){//true means this < target
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(bit.size()!=tar.bit.size())
				return bit.size()<tar.bit.size();
			else for(int i=bit.size()-1;i>=0;i--){
				if(bit[i]!=tar.bit[i])
					return bit[i]<tar.bit[i];	
			}return false;
		}
		bool equals_to(num tar){
			if(tar.basenum!=basenum)tar=tar.any2any(basenum);
			if(bit.size()!=tar.bit.size())
				return false;
			else for(int i=bit.size()-1;i>=0;i--){
				if(bit[i]!=tar.bit[i])
					return false;	
			}return true;
		}
		
		num any2any(int tarbase){
			if(tarbase<=1){
				puts("System Error - Basenum's Too Small");
				exit(1919810);
			}
			num ans("",tarbase,minu),source=(*this);
			while(source.bit[int(source.bit.size()-1)]&&int(source.bit.size())>0){
				ans.bit.push_back(source.mod(tarbase));
				source=source.dv(tarbase);
			}
			ans.delete_0();
			return ans;
		}
		#include<utility>
		pair<num,int> dv_with_rem(int tar){
			if(tar==0){
				puts("Math Error. No Result.");
				exit(1919810);
			}
			num ans("",basenum,minu*tar/abs(tar));
			int ls=bit.size()-1,remain=0;
			for(int i=ls;i>=0;i--){
				remain=remain*basenum+bit[i];
				ans.bit.push_back(remain/tar);
				remain%=tar;
			} reverse(ans.bit.begin(),ans.bit.end());
			ans.delete_0();
			return make_pair(ans,remain);
		}
		void print(){
			if(!bit.size())putchar('0');
			else if(minu==-1)putchar('-'); 
			for(int i=bit.size()-1;i>=0;i--)
				putchar(ch[bit[i]]);
			putchar('\n');
		}
		
		num operator+(const num& tar){return (*this).ad(tar);}
		num operator-(const num& tar){return (*this).mi(tar);}
		num operator*(const num& tar){return (*this).mul(tar);}
		num operator/(const num& tar){return (*this).dv(tar);}
		num operator%(const num& tar){return (*this).mod(tar);}
		
		num operator+(const int& tar){return (*this).ad(tar);}
		num operator-(const int& tar){return (*this).mi(tar);}
		num operator*(const int& tar){return (*this).mul(tar);}
		num operator/(const int& tar){return (*this).dv(tar);}
		int operator%(const int& tar){return (*this).mod(tar);}
		num operator^(const int& tar){return (*this).Pow(tar);}
		
		bool operator==(const num& tar){return (*this).equals_to(tar);}
		bool operator!=(const num& tar){return !(*this).equals_to(tar);}
		bool operator<(const num& tar){return (*this).cmp_with(tar);}
		bool operator>=(const num& tar){return !(*this).cmp_with(tar);}
		bool operator>(const num& tar){return !(*this).equals_to(tar)&&!(*this).cmp_with(tar);}
		bool operator<=(const num& tar){return (*this).equals_to(tar)||(*this).cmp_with(tar);}
		
		num operator-(){
			num ans=(*this);
			ans.minu*=-1;
			return ans;
		}
		num operator++(){return (*this)=(*this).ad(1);}
		num operator--(){return (*this)=(*this).mi(1);}
		num operator++(int){
			num tmp=(*this);
			*this=(*this).ad(1);
			return tmp;
		}
		num operator--(int){
			num tmp=(*this);
			*this=(*this).mi(1);
			return tmp;
		}
		
		num operator+=(const num& tar){return (*this)=(*this).ad(tar);}
		num operator-=(const num& tar){return (*this)=(*this).mi(tar);}
		num operator*=(const num& tar){return (*this)=(*this).mul(tar);}
		num operator/=(const num& tar){return (*this)=(*this).dv(tar);}
		num operator%=(const num& tar){return (*this)=(*this).mod(tar);}
		
		num operator+=(const int& tar){return (*this)=(*this).ad(tar);}
		num operator-=(const int& tar){return (*this)=(*this).mi(tar);}
		num operator*=(const int& tar){return (*this)=(*this).mul(tar);}
		num operator/=(const int& tar){return (*this)=(*this).dv(tar);}
		num operator%=(const int& tar){return (*this)=num(n2s((*this).mod(tar)),basenum,minu);}
		num operator^=(const int& tar){return (*this)=(*this).Pow(tar);}
};
signed main(){
	return 0;
}

posted @   robinyqc  阅读(20)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示