You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为表示数字的unsigned char数组重载+运算符?需实现四则重载

Implementing Arithmetic Operators for a Big Integer Class Using unsigned char Arrays

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:37:33