/*
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;
}