Search code examples
c++algorithmadditionmultiprecision

Issue with function that adds large integers stored in vectors


So I' ve decided to write my own multiprecision data type. I've written a simple function that adds large numbers stored in vector<uint_fast8_t>.

vector<uint_fast8_t> Add(vector<uint_fast8_t > x, vector<uint_fast8_t > y){
    unsigned int x_size = x.size() / sizeof(uint_fast8_t);
    unsigned int y_size = y.size() / sizeof(uint_fast8_t);
    unsigned int res_size{};
    if(x_size>y_size){
        res_size = x_size;
        y.insert(y.end(),uint_fast8_t(0), res_size-y_size);
    } else{
        res_size = x_size;
        x.insert(x.end(),uint_fast8_t(0), res_size-x_size);
    }
    reverse(x.begin(), x.end());
    reverse(y.begin(), y.end());
    vector<uint_fast8_t > res(res_size, 0);
    for(unsigned int i = 0; i < res_size; ++i){
        uint_fast8_t curr = res[i] + x[i] + y[i];
        if(curr >= 10){
            if(i==res_size){
                res.push_back(uint_fast8_t(1));
            } else{
                res[i+1] = uint_fast8_t(1);
            }
            res[i] = curr - uint_fast8_t(10);
        } else{
            res[i] = curr;
        }
    }
    reverse(res.begin(), res.end());
    return res;
}

Issue This function works only for numbers from 0 to 10000000 (10000000 is vector<uint_fast8_t>{1,0,0,0,0,0,0,0}). For larger numbers the results are crazy. For example it spits out 10000000000 + 123 + = 1012300000123. Why is that happening? Edit 1 I was asked about this division x.size() / sizeof(uint_fast8_t). As far as I know it returns the size of object in bytes. I divide it by size of uint_fast8_t to get the number of elements in vector. It seemed to work well. Maybe I misunderstood something.


Solution

  • This can be expressed much simpler, using std::vector::resize, std::transform and an appropriate function object.

    using Multiprecision = std::vector<uint_fast8_t>;
    
    Multiprecision Add(Multiprecision x, Multiprecision y){
    
        auto common_size = std::max(x.size(), y.size());
        x.resize(common_size);
        y.resize(common_size);
        Multiprecision res(common_size);
    
        bool carry = false;
        std::transform(x.begin(), x.end(), y.begin(), res.begin(), [&carry](uint_fast8_t x, uint_fast8_t y){ 
            uint_fast8_t value = x + y + carry; 
            carry = (value >= 10);
            return value - (carry * 10);
        });
    
        return res;
    }