📄 bigint.cpp
字号:
// if signs aren't equal, self < rhs only if self is negative if (IsNegative() != rhs.IsNegative()) { return IsNegative(); } // if # digits aren't the same must check # digits and sign if (NumDigits() != rhs.NumDigits()) { return (NumDigits() < rhs.NumDigits() && IsPositive()) || (NumDigits() > rhs.NumDigits() && IsNegative()); } // assert: # digits same, signs the same int k; int len = NumDigits(); for(k=len-1; k >= 0; k--) { if (GetDigit(k) < rhs.GetDigit(k)) return IsPositive(); if (GetDigit(k) > rhs.GetDigit(k)) return IsNegative(); } return false; // self == rhs}bool operator > (const BigInt & lhs, const BigInt & rhs)// postcondition: return true if lhs > rhs, else returns false{ return rhs < lhs;}bool operator <= (const BigInt & lhs, const BigInt & rhs)// postcondition: return true if lhs <= rhs, else returns false{ return lhs == rhs || lhs < rhs;}bool operator >= (const BigInt & lhs, const BigInt & rhs)// postcondition: return true if lhs >= rhs, else returns false{ return lhs == rhs || lhs > rhs;}void BigInt::Normalize()// postcondition: all leading zeros removed{ int k; int len = NumDigits(); for(k=len-1; k >= 0; k--) // find a non-zero digit { if (GetDigit(k) != 0) break; myNumDigits--; // "chop" off zeros } if (k < 0) // all zeros { myNumDigits = 1; mySign = positive; }}const BigInt & BigInt::operator *=(int num)// postcondition: returns num * value of BigInt after multiplication{ int carry = 0; int product; // product of num and one digit + carry int k; int len = NumDigits(); if (0 == num) // treat zero as special case and stop { *this = 0; return *this; } if (BASE < num|| num < 0) // handle pre-condition failure { *this *= BigInt(num); return *this; } if (1 == num) // treat one as special case, no work { return *this; } for(k=0; k < len; k++) // once for each digit { product = num * GetDigit(k) + carry; carry = product/BASE; ChangeDigit(k,product % BASE); } while (carry != 0) // carry all digits { AddSigDigit(carry % BASE); carry /= BASE; } return *this;}BigInt operator *(const BigInt & a, int num)// postcondition: returns a * num{ BigInt result(a); result *= num; return result;}BigInt operator *(int num, const BigInt & a)// postcondition: returns num * a{ BigInt result(a); result *= num; return result;}const BigInt & BigInt::operator *=(const BigInt & rhs)// postcondition: returns value of bigint * rhs after multiplication{ // uses standard "grade school method" for multiplying if (IsNegative() != rhs.IsNegative()) { mySign = negative; } else { mySign = positive; } BigInt self(*this); // copy of self BigInt sum(0); // to accumulate sum int k; int len = rhs.NumDigits(); // # digits in multiplier for(k=0; k < len; k++) { sum += self * rhs.GetDigit(k); // k-th digit * self self *= BASE; // add a zero } *this = sum; return *this;}BigInt operator *(const BigInt & lhs, const BigInt & rhs)// postcondition: returns a bigint whose value is lhs * rhs{ BigInt result(lhs); result *= rhs; return result;}int BigInt::NumDigits() const// postcondition: returns # digits in BigInt{ return myNumDigits;}int BigInt::GetDigit(int k) const// precondition: 0 <= k < NumDigits()// postcondition: returns k-th digit// (0 if precondition is false)// Note: 0th digit is least significant digit{ if (0 <= k && k < NumDigits()) { return myDigits[k] - '0'; } return 0;}void BigInt::ChangeDigit(int k, int value)// precondition: 0 <= k < NumDigits()// postcondition: k-th digit changed to value// Note: 0th digit is least significant digit{ if (0 <= k && k < NumDigits()) { myDigits[k] = char('0' + value); } else { cerr << "error changeDigit " << k << " " << myNumDigits << endl; }}void BigInt::AddSigDigit(int value)// postcondition: value added to BigInt as most significant digit// Note: 0th digit is least significant digit{ if (myNumDigits >= myDigits.length()) { myDigits.resize(myDigits.length() * 2); } myDigits[myNumDigits] = char('0' + value); myNumDigits++;}bool BigInt::IsNegative() const// postcondition: returns true iff BigInt is negative{ return mySign == negative;}bool BigInt::IsPositive() const// postcondition: returns true iff BigInt is positive{ return mySign == positive;}void BigInt::DivideHelp(const BigInt & lhs, const BigInt & rhs, BigInt & quotient, BigInt & remainder)// postcondition: quotient = lhs / rhs// remainder = lhs % rhs { if (lhs < rhs) // integer division yields 0 { // so avoid work and return quotient = 0; remainder = lhs; return; } else if (lhs == rhs) // again, avoid work in special case { quotient = 1; remainder = 0; return; } BigInt dividend(lhs); // make copies because of const-ness BigInt divisor(rhs); quotient = remainder = 0; int k,trial; int zeroCount = 0; // pad divisor with zeros until # of digits = dividend while (divisor.NumDigits() < dividend.NumDigits()) { divisor *= BASE; zeroCount++; } // if we added one too many zeros chop one off if (divisor > dividend) { divisor /= BASE; zeroCount--; } // algorithm: make a guess for how many times dividend part // goes into divisor, adjust the guess, subtract out and repeat int divisorSig = divisor.GetDigit(divisor.NumDigits()-1); int dividendSig; BigInt hold; for(k=0; k <= zeroCount; k++) { dividendSig = dividend.GetDigit(dividend.NumDigits()-1); trial = (dividendSig*BASE + dividend.GetDigit(dividend.NumDigits()-2)) /divisorSig; if (BASE <= trial) // stay within base { trial = BASE-1; } while ((hold = divisor * trial) > dividend) { trial--; } // accumulate quotient by adding digits to quotient // and chopping them off of divisor after adjusting dividend quotient *= BASE; quotient += trial; dividend -= hold; divisor /= BASE; divisorSig = divisor.GetDigit(divisor.NumDigits()-1); } remainder = dividend;}const BigInt & BigInt::operator /=(const BigInt & rhs)// postcondition: return BigInt / rhs after modification{ BigInt quotient,remainder; bool resultNegative = (IsNegative() != rhs.IsNegative()); mySign = positive; // force myself positive // DivideHelp does all the work if (rhs.IsNegative()) { DivideHelp(*this,-1*rhs,quotient,remainder); } else { DivideHelp(*this,rhs,quotient,remainder); } *this = quotient; mySign = resultNegative ? negative : positive; Normalize(); return *this;}BigInt operator / (const BigInt & lhs, const BigInt & rhs)// postcondition: return lhs / rhs{ BigInt result(lhs); result /= rhs; return result;}const BigInt & BigInt::operator /=(int num)// precondition: 0 < num < BASE // postcondition: returns BigInt/num after modification{ int carry = 0; int quotient; int k; int len = NumDigits(); if (num > BASE) // check precondition { return operator /= (BigInt(num)); } if (0 == num) // handle division by zero { cerr << "division by zero error" << endl; abort(); } else { for(k=len-1; k >= 0; k--) // once for each digit { quotient = (BASE*carry + GetDigit(k)); carry = quotient % num; ChangeDigit(k, quotient / num); } } Normalize(); return *this;}BigInt operator /(const BigInt & a, int num)// postcondition: returns a / num { BigInt result(a); result /= num; return result;}BigInt operator %(const BigInt & lhs, const BigInt & rhs)// postcondition: returns lhs % rhs { BigInt result(lhs); result %= rhs; return result;}const BigInt & BigInt::operator %=(const BigInt & rhs)// postcondition: returns BigInt % rhs after modification { BigInt quotient,remainder; bool resultNegative = IsNegative(); // DivideHelp does all the work if (rhs.IsNegative()) { DivideHelp(*this,-1 * rhs,quotient,remainder); } else { DivideHelp(*this,rhs,quotient,remainder); } *this = remainder; mySign = resultNegative ? negative : positive; return *this;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -