0

I am currently taking an online data structures course using C++ and I'm working on a personal project to help me better understand the basics. The project I'm working on is an implementation of a bigint class, a class that supports storing and calculation of arbitrary-precision integers using arrays and not vectors or strings. I am struggling with the implementation of the major arithmetic operators.

The numbers are stored in the array from least to most significant digit (201 would be stored as {1,0,2}) and the calculations are performed in this order as well.

I have found some material relating to this but the vast majority use vectors/strings and did not help me much. A couple of other resources, such as this and this did help, but did not work when I tried to implement them in my code. For example, this code to implement the addition operator does not work and I either get a bad_alloc exception or the answer is just way wrong, but I can't seem to figure out why or how to solve it and I've been at it for days now:

bigint& operator+(const bigint& lhs, const bigint& rhs){
    bool minus_sign = rhs.is_negative();
    size_t amt_used = 0;    // to keep track of items in the array

    // initial size and size of resulting array
    // set initial size to the size of the larger array
    // set result_size to ini size plus one in case of carry
    size_t ini_size = lhs.get_digit_count() > rhs.get_digit_count() ?
                                lhs.get_digit_count() : rhs.get_digit_count();
    const size_t INITIAL_SIZE = ini_size;
    const size_t RESULT_SIZE = INITIAL_SIZE+1;

    uint8_t temp[RESULT_SIZE],  // temporary array
            result_arr[RESULT_SIZE],
            lhs_arr[INITIAL_SIZE], rhs_arr[INITIAL_SIZE]; // new arrays for lhs/rhs of the same size to avoid overflow if one is smaller

    //assign corresponding values to the new arrays
    for (size_t i = 0; i < lhs.get_digit_count(); i++){
        lhs_arr[i] = lhs.get_digit(i);
    }

    for (size_t i = 0; i < rhs.get_digit_count(); i++){
        rhs_arr[i] = rhs.get_digit(i);
    }

    // perform addition
    int carry = 0;  //carry variable
    size_t j = 0;
    for ( ; j < INITIAL_SIZE; j++){
        uint8_t sum = lhs_arr[j] + rhs_arr[j] + carry;

        if (sum > 9){
            result_arr[j] = sum - 10;
            carry = 1;
            amt_used++;
        }
        else{
            result_arr[j] = sum;
            carry = 0;
            amt_used++;
        }
    }

    if (carry == 1){
        result_arr[j] = 1;
        amt_used++;
    }

    // flip the array to most sig to least sig, since the constructor performs a switch to least-most sig.
    size_t decrement_index = amt_used - 1;
    for (int i = 0; i < RESULT_SIZE; i++){
        temp[i] = result_arr[decrement_index];
        decrement_index--;
    }

    for (int i = 0; i < RESULT_SIZE; i++){
        result_arr[i] = temp[i];
    }

    // create new bigint using the just-flipped array and return it
    bigint result(result_arr, amt_used, minus_sign);

    return result;
}

Here's the error I get: Thread 1: EXC_BAD_ACCESS (code=1, address=0x5)

Either that or I get a really large number when I'm just adding 8700 + 2100

babakahn
  • 25
  • 1
  • 5
  • 1
    You're returning a reference to `result`. Don't do that, do what the example does. – molbdnilo Mar 22 '18 at 09:33
  • `uint8_t temp[RuntimeValue];` is not valid C++, but an extension named VLA. `std::vector` is a good correct alternative. – Jarod42 Mar 22 '18 at 09:36
  • Your array for the result is one too small: both 8700 and 2100 have 4 digits, but you need 5 digits for the result. So allocate maximum digit count + 1, calculate and if necessary, remove any top 0 digit. – Rudy Velthuis Mar 25 '18 at 16:38

1 Answers1

0

There are several issues with this code.

The use of the VLA extension (for temp etc) is not standard C++. These stack based arrays are not initialized, so they will contain random data. When you fill these arrays with data, you are not assigning to every element. This results in the garbage results when, for example, the left number is shorter than the right (so that several elements of lhs_arr have garbage data in them). These bad values will then be used in the addition array. Using std::vector would be standard compliant and result in the vector elements all being initialized to something appropriate (like 0). This could be where your "really large number" comes from.

When you "flip the array", decrement_index can be negative if not all of the result slots were used. This could be a cause of you EXC_BAD_ACCESS crashes.

Returning a reference to a local variable results in Undefined Behavior, since that local will be destroyed when the function returns resulting in a dangling reference. This could be a cause of either of your stated problems.

Your handling of negative numbers is completely wrong, since you don't really handle them at all.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
  • thank you. I know I need to implement the negatives but I will do that once I complete the subtraction function. So basically what you're saying is it's not possible to implement this class without using vectors/strings? – babakahn Mar 23 '18 at 00:03
  • @babakahn It is possible, but using vectors makes some things much simpler. – 1201ProgramAlarm Mar 23 '18 at 01:41