2

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.

A. Szokalski
  • 65
  • 1
  • 6
  • 2
    It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: [How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – NathanOliver Oct 30 '18 at 15:35
  • 2
    `else{ res_size = x_size; x.insert(x.end(),uint_fast8_t(0), res_size-x_size);` doesn't look right. – NathanOliver Oct 30 '18 at 15:35
  • 3
    And `x.size() / sizeof(uint_fast8_t)` also looks wrong. What's the purpose of that? – Some programmer dude Oct 30 '18 at 15:37
  • The opening division is definitely wrong; it's unnecessary, as is pre-sizing the resulting vector. – WhozCraig Oct 30 '18 at 15:38
  • 1
    `vector::size()` returns the number of elements in the vector, not the number of bytes that it occupies. Your division is redundant. – 3Dave Oct 30 '18 at 17:57
  • Thanks! I'll fix that – A. Szokalski Oct 31 '18 at 10:50

2 Answers2

1

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;
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Thanks for help! Honestly I don't understand half of the code in your function (I'll have to read documentation for these functions). But thanks anyway, this solution looks way better than mine. – A. Szokalski Oct 31 '18 at 12:26
0

Ok I fixed it

Thank you for pointing out some mistakes in my code. I am a begginer so it's important to me. With your help I managed to fix the issue. I think the problem was in pre sizing the vector. Here's working code: (I think the insert function can insert many zeros without for loop. I'll check an maybe replace it)

vector<uint_fast8_t> Add(vector<uint_fast8_t > x, vector<uint_fast8_t > y) {
unsigned long x_size = x.size();
unsigned long y_size = y.size();
unsigned long res_size{};
uint_fast8_t curr = 0;
vector<uint_fast8_t > res{};

if(x_size>y_size){
    res_size = x_size;
    for(unsigned int i = 0; i < res_size - y_size; ++i){
        y.insert(y.begin(), uint_fast8_t(0));
    }
} else{
    res_size = y_size;
    for(unsigned int j = 0; j < res_size - x_size; ++j){
        x.insert(x.begin(), uint_fast8_t(0));
    }
}

reverse(x.begin(), x.end());
reverse(y.begin(), y.end());

for(unsigned int k = 0; k < res_size; ++k){
    curr += x[k] + y[k];
    if(curr >= 10){
        res.push_back(curr - uint_fast8_t(10));
        curr = 1;
        if(k == res_size -1){
            res.push_back(curr);
        }
    } else{
        res.push_back(curr);
        curr = 0;
    }
}

reverse(res.begin(), res.end());

return res;

}

A. Szokalski
  • 65
  • 1
  • 6