如何为表示数字的unsigned char数组重载+运算符?需实现四则重载
Hey there! Let's work through completing your decimal class with all the arithmetic operators. First, let's fix the existing code and finish the addition operator, then move on to subtraction, multiplication, and division.
First: Fix the Constructor
Your current constructor stores ASCII characters instead of numeric digits, which will break arithmetic operations. Let's adjust it to store actual 0-9 values, and store digits in reverse order (least significant digit at index 0) to make arithmetic easier:
#include <iostream> #include <cstring> #include <algorithm> using namespace std; class decimal { private: unsigned char dec[100]; size_t size; // Helper constructor to create decimal from a digit array and size decimal(unsigned char digits[], size_t len) { memset(dec, 0, sizeof(dec)); // Initialize all elements to 0 size = len; for (size_t i = 0; i < len; ++i) { dec[i] = digits[i]; } } public: decimal(const char* get) { memset(dec, 0, sizeof(dec)); size = strlen(get); // Store digits in reverse order (LSB at index 0) for (int i = size - 1; i >= 0; --i) { dec[size - 1 - i] = get[i] - '0'; // Convert char to numeric digit } } // Helper to print the number correctly void print() const { for (int i = size - 1; i >= 0; --i) { cout << (char)(dec[i] + '0'); } cout << endl; }
1. Complete the Addition Operator
The addition operator iterates through each digit, sums them with carry, and builds the result:
friend decimal operator+(const decimal& a, const decimal& b) { unsigned char resultDigits[101] = {0}; // Extra space for final carry size_t maxSize = max(a.size, b.size); unsigned char carry = 0; for (size_t i = 0; i < maxSize; ++i) { unsigned char digitA = (i < a.size) ? a.dec[i] : 0; unsigned char digitB = (i < b.size) ? b.dec[i] : 0; unsigned char sum = digitA + digitB + carry; resultDigits[i] = sum % 10; carry = sum / 10; } size_t resultSize = maxSize; if (carry != 0) { resultDigits[maxSize] = carry; resultSize++; } return decimal(resultDigits, resultSize); }
Quick Explanation:
- We use a temporary array to hold sum digits, with extra space for a final carry.
- For each position, sum digits from both operands plus carry, then split into current digit and new carry.
- If carry remains after processing all digits, add it as an extra digit to the result.
2. Implement the Subtraction Operator
First, add a helper to compare numbers (to avoid negative results), then handle borrow during subtraction:
private: // Helper to check if a >= b static bool isGreaterOrEqual(const decimal& a, const decimal& b) { if (a.size != b.size) return a.size > b.size; // Same size: compare from most significant digit to least for (int i = a.size - 1; i >= 0; --i) { if (a.dec[i] != b.dec[i]) return a.dec[i] > b.dec[i]; } return true; // Equal } public: friend decimal operator-(const decimal& a, const decimal& b) { if (!isGreaterOrEqual(a, b)) { cerr << "Error: Subtraction result is negative" << endl; return decimal("0"); } unsigned char resultDigits[100] = {0}; unsigned char borrow = 0; for (size_t i = 0; i < a.size; ++i) { unsigned char digitA = a.dec[i]; unsigned char digitB = (i < b.size) ? b.dec[i] : 0; // Handle borrow from previous step if (digitA < borrow) { digitA += 10; borrow = 1; } else { digitA -= borrow; borrow = 0; } // Handle borrow for current digit if (digitA < digitB) { digitA += 10; borrow = 1; } resultDigits[i] = digitA - digitB; } // Remove leading zeros (trailing in reversed array) size_t resultSize = a.size; while (resultSize > 1 && resultDigits[resultSize - 1] == 0) { resultSize--; } return decimal(resultDigits, resultSize); }
3. Implement the Multiplication Operator
Use long multiplication: multiply each digit pair, accumulate results in the correct positions, then handle carry:
friend decimal operator*(const decimal& a, const decimal& b) { unsigned char resultDigits[200] = {0}; // Max size: a.size + b.size size_t resultSize = a.size + b.size; for (size_t i = 0; i < a.size; ++i) { unsigned char carry = 0; for (size_t j = 0; j < b.size; ++j) { unsigned long long product = resultDigits[i + j] + (a.dec[i] * b.dec[j]) + carry; resultDigits[i + j] = product % 10; carry = product / 10; } if (carry != 0) { resultDigits[i + b.size] += carry; } } // Trim leading zeros while (resultSize > 1 && resultDigits[resultSize - 1] == 0) { resultSize--; } return decimal(resultDigits, resultSize); }
4. Implement the Division Operator
Use trial division: build the quotient digit by digit by checking how many times the divisor fits into portions of the dividend:
friend decimal operator/(const decimal& dividend, const decimal& divisor) { // Handle division by zero if (divisor.size == 1 && divisor.dec[0] == 0) { cerr << "Error: Division by zero" << endl; return decimal("0"); } // Dividend smaller than divisor: result is 0 if (!isGreaterOrEqual(dividend, divisor)) { return decimal("0"); } decimal temp("0"); unsigned char quotientDigits[100] = {0}; size_t quotientSize = dividend.size; // Process dividend from MSB to LSB for (int i = dividend.size - 1; i >= 0; --i) { // Shift temp left (multiply by 10) and add current digit unsigned char tempDigits[101] = {0}; for (size_t j = temp.size; j > 0; --j) { tempDigits[j] = temp.dec[j-1]; } tempDigits[0] = dividend.dec[i]; size_t tempSize = temp.size + 1; while (tempSize > 1 && tempDigits[tempSize - 1] == 0) tempSize--; temp = decimal(tempDigits, tempSize); // Count how many times divisor fits into temp int count = 0; while (isGreaterOrEqual(temp, divisor)) { temp = temp - divisor; count++; } quotientDigits[i] = count; } // Trim leading zeros while (quotientSize > 1 && quotientDigits[quotientSize - 1] == 0) quotientSize--; // Reverse quotient digits to match our reversed storage format unsigned char reversedQuotient[100] = {0}; for (size_t i = 0; i < quotientSize; ++i) { reversedQuotient[i] = quotientDigits[quotientSize - 1 - i]; } return decimal(reversedQuotient, quotientSize); }
Test the Class
Add a main function to verify all operators:
~decimal() {} }; int main() { decimal a("123456"); decimal b("7890"); cout << "a = "; a.print(); cout << "b = "; b.print(); decimal sum = a + b; cout << "a + b = "; sum.print(); decimal diff = a - b; cout << "a - b = "; diff.print(); decimal product = a * b; cout << "a * b = "; product.print(); decimal quotient = a / b; cout << "a / b = "; quotient.print(); return 0; }
Notes:
- The fixed-size 100-digit array can be adjusted for larger numbers.
- Error handling is basic here; you can enhance it with exceptions if needed.
- For better division performance with very large numbers, consider implementing binary division or Newton-Raphson methods.
内容的提问来源于stack exchange,提问作者Roman

