#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct DecimalBig {
vector<int> intPart;
vector<int> decPart;
int sign;
int decLen;
DecimalBig() : sign(1), decLen(250) {}
DecimalBig(long long x, int dl = 250) : decLen(dl) {
sign = 1;
if (x < 0) {
sign = -1;
x = -x;
}
intPart.clear();
decPart.clear();
if (x == 0) intPart.push_back(0);
while (x) {
intPart.push_back(x % 10);
x /= 10;
}
}
DecimalBig(const string &s, int dl = 250) : decLen(dl) {
sign = 1;
intPart.clear();
decPart.clear();
int dotPos = -1;
int st = 0;
if (s[0] == '-') {
sign = -1;
st = 1;
}
for (int i = st; i < s.size(); i++) {
if (s[i] == '.') {
dotPos = i;
break;
}
}
if (dotPos == -1) {
for (int i = s.size() - 1; i >= st; i--)
intPart.push_back(s[i] - '0');
} else {
for (int i = dotPos - 1; i >= st; i--)
intPart.push_back(s[i] - '0');
for (int i = dotPos + 1; i < s.size() && decPart.size() < decLen; i++)
decPart.push_back(s[i] - '0');
}
trim();
}
void trim() {
while (intPart.size() > 1 && intPart.back() == 0)
intPart.pop_back();
while (decPart.size() > 0 && decPart.back() == 0)
decPart.pop_back();
if (intPart.size() == 1 && intPart[0] == 0 && decPart.empty())
sign = 1;
}
void fillDec(int len) {
while (decPart.size() < len) decPart.push_back(0);
}
void roundDec(int keep) {
if ((int)decPart.size() <= keep) return;
int carry = decPart[keep] >= 5 ? 1 : 0;
decPart.resize(keep);
int pos = 0;
while (carry && pos < decPart.size()) {
int sum = decPart[pos] + carry;
decPart[pos] = sum % 10;
carry = sum / 10;
pos++;
}
if (carry) {
pos = 0;
while (carry && pos < intPart.size()) {
int sum = intPart[pos] + carry;
intPart[pos] = sum % 10;
carry = sum / 10;
pos++;
}
if (carry) intPart.push_back(1);
}
trim();
}
vector<int> toAllInt() const {
vector<int> res = intPart;
for (auto c : decPart) res.insert(res.begin(), c);
return res;
}
bool absGreater(const DecimalBig &b) const {
int maxDec = max(decPart.size(), b.decPart.size());
DecimalBig aTmp = *this, bTmp = b;
aTmp.fillDec(maxDec);
bTmp.fillDec(maxDec);
vector<int> aAll = aTmp.toAllInt();
vector<int> bAll = bTmp.toAllInt();
if (aAll.size() != bAll.size()) return aAll.size() > bAll.size();
for (int i = aAll.size() - 1; i >= 0; i--)
if (aAll[i] != bAll[i]) return aAll[i] > bAll[i];
return false;
}
bool absEqual(const DecimalBig &b) const {
return !absGreater(b) && !b.absGreater(*this);
}
DecimalBig absAdd(const DecimalBig &b) const {
DecimalBig res;
res.decLen = max(decLen, b.decLen);
int maxDec = max(decPart.size(), b.decPart.size());
DecimalBig aTmp = *this, bTmp = b;
aTmp.fillDec(maxDec);
bTmp.fillDec(maxDec);
vector<int> aAll = aTmp.toAllInt();
vector<int> bAll = bTmp.toAllInt();
vector<int> sumAll;
int carry = 0;
int maxLen = max(aAll.size(), bAll.size());
for (int i = 0; i < maxLen || carry; i++) {
int va = (i < aAll.size()) ? aAll[i] : 0;
int vb = (i < bAll.size()) ? bAll[i] : 0;
int s = va + vb + carry;
sumAll.push_back(s % 10);
carry = s / 10;
}
res.decPart.clear();
res.intPart.clear();
for (int i = 0; i < maxDec && i < sumAll.size(); i++)
res.decPart.push_back(sumAll[i]);
for (int i = maxDec; i < sumAll.size(); i++)
res.intPart.push_back(sumAll[i]);
res.roundDec(res.decLen);
return res;
}
DecimalBig absSub(const DecimalBig &b) const {
DecimalBig res;
res.decLen = max(decLen, b.decLen);
int maxDec = max(decPart.size(), b.decPart.size());
DecimalBig aTmp = *this, bTmp = b;
aTmp.fillDec(maxDec);
bTmp.fillDec(maxDec);
vector<int> aAll = aTmp.toAllInt();
vector<int> bAll = bTmp.toAllInt();
vector<int> subAll;
int borrow = 0;
for (int i = 0; i < aAll.size(); i++) {
int va = aAll[i] - borrow;
int vb = (i < bAll.size()) ? bAll[i] : 0;
borrow = 0;
if (va < vb) {
va += 10;
borrow = 1;
}
subAll.push_back(va - vb);
}
res.decPart.clear();
res.intPart.clear();
for (int i = 0; i < maxDec && i < subAll.size(); i++)
res.decPart.push_back(subAll[i]);
for (int i = maxDec; i < subAll.size(); i++)
res.intPart.push_back(subAll[i]);
res.roundDec(res.decLen);
return res;
}
DecimalBig operator+(const DecimalBig &b) const {
DecimalBig res;
if (sign == b.sign) {
res = absAdd(b);
res.sign = sign;
} else {
if (absGreater(b)) {
res = absSub(b);
res.sign = sign;
} else {
res = b.absSub(*this);
res.sign = -b.sign;
}
}
return res;
}
DecimalBig operator-(const DecimalBig &b) const {
DecimalBig tmp = b;
tmp.sign *= -1;
return *this + tmp;
}
DecimalBig operator*(const DecimalBig &b) const {
DecimalBig res;
res.decLen = decLen + b.decLen;
res.sign = sign * b.sign;
vector<int> aAll = toAllInt();
vector<int> bAll = b.toAllInt();
vector<int> mulAll(aAll.size() + bAll.size(), 0);
for (int i = 0; i < aAll.size(); i++) {
int carry = 0;
for (int j = 0; j < bAll.size() || carry; j++) {
int vb = (j < bAll.size()) ? bAll[j] : 0;
long long val = mulAll[i + j] + 1LL * aAll[i] * vb + carry;
mulAll[i + j] = val % 10;
carry = val / 10;
}
}
int totalDec = decPart.size() + b.decPart.size();
res.decPart.clear();
res.intPart.clear();
for (int i = 0; i < totalDec && i < mulAll.size(); i++)
res.decPart.push_back(mulAll[i]);
for (int i = totalDec; i < mulAll.size(); i++)
res.intPart.push_back(mulAll[i]);
res.roundDec(decLen);
res.trim();
return res;
}
using BigIntVec = vector<int>;
static bool bigVecCmp(const BigIntVec &a, const BigIntVec &b) {
if (a.size() != b.size()) return a.size() > b.size();
for (int i = a.size()-1; i >= 0; i--)
if (a[i] != b[i]) return a[i] > b[i];
return false;
}
static BigIntVec bigVecSub(const BigIntVec &a, const BigIntVec &b) {
BigIntVec res;
int bor = 0;
for (int i = 0; i < a.size(); i++) {
int va = a[i] - bor;
int vb = (i < b.size()) ? b[i] : 0;
bor = 0;
if (va < vb) { va += 10; bor = 1; }
res.push_back(va - vb);
}
while (res.size()>1 && res.back()==0) res.pop_back();
return res;
}
static BigIntVec bigVecMul10(BigIntVec x) {
x.insert(x.begin(), 0);
return x;
}
static int tryDiv(BigIntVec &rem, const BigIntVec &div)
{
int l=0,r=9,ans=0;
BigIntVec base=div;
while(l<=r)
{
int mid=(l+r)/2;
BigIntVec mul=base;
int carry=0;
for(auto &x:mul)
{
long long v=1LL*x*mid+carry;
x=v%10;
carry=v/10;
}
if(carry) mul.push_back(carry);
if(bigVecCmp(rem,mul)||!bigVecCmp(mul,rem))
{
ans=mid;
l=mid+1;
}
else
{
r=mid-1;
}
}
BigIntVec sub;
int borrow=0;
for(int i=0;i<rem.size();i++)
{
long long val=1LL*div[i]*ans+borrow;
int d=rem[i]-(val%10);
borrow=val/10;
if(d<0) {d+=10;borrow++;}
sub.push_back(d);
}
while(sub.size()>1&&sub.back()==0) sub.pop_back();
rem=sub;
return ans;
}
DecimalBig operator/(const DecimalBig &b) const {
if (b.intPart.size()==1 && b.intPart[0]==0 && b.decPart.empty()) {
cerr<<"Error: Division by zero!"<<endl;
exit(1);
}
DecimalBig res;
res.decLen = decLen;
res.sign = sign * b.sign;
BigIntVec A = this->toAllInt();
BigIntVec B = b.toAllInt();
int shiftDec = (int)decPart.size() - (int)b.decPart.size();
reverse(A.begin(), A.end());
reverse(B.begin(), B.end());
BigIntVec qInt, rem;
for (int d : A) {
rem.push_back(d);
reverse(rem.begin(), rem.end());
int num = tryDiv(rem, B);
qInt.push_back(num);
reverse(rem.begin(), rem.end());
}
reverse(qInt.begin(), qInt.end());
while(qInt.size()>1 && qInt.back()==0) qInt.pop_back();
res.intPart = qInt;
vector<int> qDec;
while((int)qDec.size() < res.decLen) {
rem = bigVecMul10(rem);
int num = tryDiv(rem, B);
qDec.push_back(num);
}
res.decPart = qDec;
if(shiftDec > 0) {
for(int i=0;i<shiftDec;i++){
if(res.decPart.empty()) break;
res.intPart.insert(res.intPart.begin(), res.decPart[0]);
res.decPart.erase(res.decPart.begin());
}
}else if(shiftDec < 0){
int s = -shiftDec;
for(int i=0;i<s;i++){
if(res.intPart.size()<=1 && res.intPart[0]==0) break;
res.decPart.insert(res.decPart.begin(), res.intPart[0]);
res.intPart.erase(res.intPart.begin());
}
}
res.roundDec(res.decLen);
res.trim();
return res;
}
DecimalBig operator%(const DecimalBig &b) const {
DecimalBig q = *this / b;
DecimalBig res = *this - q * b;
return res;
}
DecimalBig& operator+=(const DecimalBig &b) {
*this = *this + b;
return *this;
}
DecimalBig& operator-=(const DecimalBig &b) {
*this = *this - b;
return *this;
}
DecimalBig& operator*=(const DecimalBig &b) {
*this = *this * b;
return *this;
}
DecimalBig& operator/=(const DecimalBig &b) {
*this = *this / b;
return *this;
}
DecimalBig& operator%=(const DecimalBig &b) {
*this = *this % b;
return *this;
}
bool operator>(const DecimalBig &b) const {
if (sign == 1 && b.sign == -1) return true;
if (sign == -1 && b.sign == 1) return false;
if (sign == 1) return absGreater(b);
else return b.absGreater(*this);
}
bool operator<(const DecimalBig &b) const { return b > *this; }
bool operator==(const DecimalBig &b) const {
if (sign != b.sign) return false;
return absEqual(b);
}
bool operator!=(const DecimalBig &b) const { return !(*this == b); }
bool operator>=(const DecimalBig &b) const { return (*this > b) || (*this == b); }
bool operator<=(const DecimalBig &b) const { return (*this < b) || (*this == b); }
friend ostream &operator<<(ostream &os, const DecimalBig &x) {
if (x.sign == -1) os << '-';
if (x.intPart.empty()) os << 0;
else for (int i = x.intPart.size() - 1; i >= 0; i--) os << x.intPart[i];
if (!x.decPart.empty()) {
os << '.';
for (int v : x.decPart) os << v;
}
return os;
}
friend istream &operator>>(istream &is, DecimalBig &x) {
string s;
is >> s;
x = DecimalBig(s, x.decLen);
return is;
} DecimalBig& operator++(){
*this=*this+DecimalBig("1");
return *this;
}
DecimalBig operator++(int){
DecimalBig tmp=*this;
++(*this);
return tmp;
}
DecimalBig& operator--(){
*this=*this-DecimalBig("1");
return *this;
}
DecimalBig operator--(int){
DecimalBig tmp=*this;
--(*this);
return tmp;
}
};
int main() {
DecimalBig a("10", 8);
DecimalBig b("3", 8);
cout << "初始 a = " << a << endl;
a += b;
cout << "a += 3 -> " << a << endl;
a -= DecimalBig("2");
cout << "a -= 2 -> " << a << endl;
a *= DecimalBig("1.5");
cout << "a *= 1.5 -> " << a << endl;
a /= DecimalBig("2");
cout << "a /= 2 -> " << a << endl;
a %= DecimalBig("4");
cout << "a %= 4 -> " << a << endl;
DecimalBig x("10"),y("10"),z("3");
DecimalBig ans = x + y / z;
cout<<"10 + 10 / 3 = "<<ans<<endl;
DecimalBig ans2 = (x+y)/z;
cout<<"(10+10)/3 = "<<ans2<<endl;
return 0;
}
@