Question

I'm doing some very basic Linear Algebra and I'm probably missing the point completely here.

Let's say I have the following matrices:

v1 = [5, 8]
v2 = [3, 4]
v3 = [4, 4]
v4 = [2, 1]

Expected output:

M1 = [5 - 3, 8 - 4] = [2, 4] 
M2 = [4 - 2, 4 - 1] = [2, 3]

Actual output:

0 0 
0 0 
2 4 
-1 0 
2 3 

Here is the code:

std::vector<double> calculate(std::vector<double> values, std::vector<double> values2)
{
    std::vector<double> vel(2, 0);

    for(unsigned i=0; (i < values.size()); i++)
    {
        vel[i] = values[i] - values2[i];
    }

    return vel;
}



  std::vector<std::vector<double> > values = { {5,8}, {3, 4}, {4, 4}, {2, 1}};

    std::vector<std::vector<double> > v;

    v.resize(2);

    for(unsigned i=0; (i < values.size()-1); i++)
    {   
        v[i].resize(2);
        v.push_back(calculate(values[i], values[i + 1]));
        //v[i] = calculate(values[i], values[i + 1]);
    }

    for(unsigned i=0; (i < v.size()); i++)
    {
        for(unsigned j=0; (j < v[i].size()); j++)
        {
            std::cout << v[i][j] << " ";
        }
        std::cout << std::endl;
    }

The problem being is that, the following should iterate over 4 times, calculating the 4 matrices, and the final resulting 2D vector should only contain 2 values.

I'm probably missing something stupid.

Was it helpful?

Solution

v.resize(2); // now it contains `{{} {}}`.
for(unsigned i=0; (i < values.size()-1); i++) //for each input except the last (3 iterations)
                    //starting with {5,8} and {3,4}
    v[i].resize(2); //resize one of the vectors already in v to 2 
                    //now v contains {{0,0}, {}
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations
                    //now v contains {{0,0}, {}, {2,4}}
for(............. (i < values.size()-1); i++)
                    //next the middle pair of inputs  {3,4} and {4,4}
    v[i].resize(2); //resize one of the vectors already in v to 2 
                    //now v contains {{0,0}, {0,0}, {2,4}}
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations
                    //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}}
for(............. (i < values.size()-1); i++)
                    //finally the last pair of inputs  {4,4} and {2,1}
    v[i].resize(2); //resize the {2,4} to 2, but it was already two
                    //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}}
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations
                    //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}, {2,3}}
for(............. (i < values.size()-1); ....) //done iterating

Do you have a debugger? It's really important to learn how to step through code like this, have someone show you, or find a tutorial. Stepping through this code in a debugger would have made it obvious what was going on to you.

Luckily, the code is REALLY easy to fix:

std::vector<std::vector<double> > v;

for(unsigned i=0; i<values.size()-1; i+=2) //NOTE: i+=2!!!
{   
    v.push_back(calculate(values[i], values[i + 1]));
}

Proof: http://coliru.stacked-crooked.com/a/827a0183f1e7c582

OTHER TIPS

for(unsigned i=0; (i < values.size()-1); i++)
{   
    v[i].resize(2);
    v.push_back(calculate(values[i], values[i + 1]));
    //v[i] = calculate(values[i], values[i + 1]);
}

This loop operates on two elements of values, so the counter needs to increase by 2 per iteration. otherwise you would subtract v1-v2, v2-v3, v3-v4 and so on. Also there is no need to determine the vector size prior to the push_back (and it actually dangerous, because the index is likely out-of-bounds before the element is pushed back).

for(unsigned i=0; (i < values.size()-1); i+=2)
{   
    //v[i].resize(2);
    v.push_back(calculate(values[i], values[i + 1]));
    //v[i] = calculate(values[i], values[i + 1]);
}

As pointed out by others v.resize(2); shouldn't be there either because it just adds two empty elements initially, which you don't want.

v.resize(2);

I don't know what you were expecting the above to do, but this (coupled with the code below) is what is responsible for those first two lines of output.

for(unsigned i=0; (i < values.size()-1); i++)
{   
    v[i].resize(2);

I don't know what you were expecting the above to do, but this (coupled with the code above) is what is responsible for those first two lines of output.

Here's what's happening: Your first resize (the resize outside the loop) populates v with two empty vectors. The first two passes through the loop populate v[0] and v[1] as vectors of doubles with two elements that are both zero.

    v.push_back(calculate(values[i], values[i + 1]));

This will ultimately add three more elements to v, one being {5,8}-{3, 4}={2,4}, the next being {3,4}-{4,4}={-1,0}, and the last being {4,4}-{2,1}={2,3}. So your output should be

0 0
0 0
2 4
-1 0
2 3

To get rid of those first two lines, simply delete the two calls to resize. To get rid of the penultimate line (that -1 0 that is between the two desired lines of output), change your loop increment from one (i++) to two (i += 2).

This output

    0 0 
    0 0 
    2 4 
   -1 0 
    2 3 

can be explained very simply

At first using method resize

v.resize(2);

you added two empty std::vector in vector v.

Then in loop

for(unsigned i=0; (i < values.size()-1); i++)
{   
    v[i].resize(2);
    v.push_back(calculate(values[i], values[i + 1]));
    //v[i] = calculate(values[i], values[i + 1]);
}

you resized each of them. So now v[0] and v[1] are

0 0 
0 0 

And then you get subtraction of

values[0] - values[1]
values[1] - values[2]
values[2] - values[3]

After that vector v was appended with

    2 4 
   -1 0 
    2 3 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top