C ++ - Матричное вычитание

0

Я делаю очень базовую линейную алгебру, и я, вероятно, вообще не вижу смысла здесь.

Скажем, у меня есть следующие матрицы:

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

Ожидаемый результат:

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

Фактический выход:

0 0 
0 0 
2 4 
-1 0 
2 3 

Вот код:

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;
    }

Проблема заключается в том, что следующее следует перебрать более 4 раз, вычисляя 4 матрицы, а итоговый 2D-вектор должен содержать только 2 значения.

Мне, наверное, не хватает чего-то глупого.

  • 0
    Я думаю, что логика становится намного проще, если вы рассматриваете два вектора отдельно для каждой матрицы. Взятие одного вектора для обеих матриц делает код немного нечитаемым.
  • 3
    Вы действительно должны использовать библиотеку линейной алгебры C ++, такую как броненосец . Несмотря на название, std::vector имеет ужасный интерфейс для линейной алгебры. Конкретная проблема, с которой вы столкнулись, заключается в том, что вы путаете размеры и положения элементов.
Показать ещё 1 комментарий
Теги:
matrix
linear-algebra

4 ответа

2
Лучший ответ
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

У вас есть отладчик? Очень важно научиться, как проходить через такой код, показать кого-нибудь или найти учебник. Прохождение этого кода в отладчике сделало бы очевидным то, что происходило с вами.

К счастью, код ДЕЙСТВИТЕЛЬНО легко исправить:

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]));
}

Доказательство: http://coliru.stacked-crooked.com/a/827a0183f1e7c582

  • 0
    Эй, спасибо тебе за это. Однако это не работает. Я просто получаю 2 4 тогда как мне нужна еще одна матрица с еще 2 значениями ..
  • 0
    Вы, должно быть, изменили что-то еще. Код в этом посте работает нормально, я только что проверил: coliru.stacked-crooked.com/a/827a0183f1e7c582
1
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]);
}

Этот цикл работает с двумя элементами values, поэтому счетчик должен увеличиться на 2 за итерацию. в противном случае вы вычтите v1-v2, v2-v3, v3-v4 и т.д. Также нет необходимости определять размер вектора до push_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]);
}

Как указывалось другими v.resize(2); не должен быть там, потому что он просто добавляет два пустых элемента изначально, чего вы не хотите.

  • 0
    Здравствуйте, нет, к сожалению, это не сработало .. Просто печатает 0 0
  • 0
    @ user1326876 Исправлено что-то. Надеюсь, это работает сейчас.
Показать ещё 1 комментарий
1
v.resize(2);

Я не знаю, что вы ожидали выше, но это (в сочетании с приведенным ниже кодом) является тем, что отвечает за эти первые две строки вывода.

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

Я не знаю, что вы ожидали от вышеперечисленного, но это (в сочетании с кодом выше) является тем, что отвечает за эти первые две строки вывода.

Вот что происходит: ваш первый размер (изменение размера вне цикла) заполняет v двумя пустыми векторами. Первые два прохода через петлю заполняют v[0] и v[1] как векторы двойников с двумя элементами, которые равны нулю.

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

Это, в конечном счете, добавит еще три элемента к v, один из которых {5,8} - {3, 4} = {2,4}, следующий из которых {3,4} - {4,4} = {-1, 0}, а последнее - {4,4} - {2,1} = {2,3}. Таким образом, ваш результат должен быть

0 0
0 0
2 4
-1 0
2 3

Чтобы избавиться от этих первых двух строк, просто удалите два вызова для resize. Чтобы избавиться от предпоследней строки (-1 0 которая находится между двумя желаемыми линиями вывода), измените инкремент цикла с одного (i++) на два (i += 2).

0

Этот выход

    0 0 
    0 0 
    2 4 
   -1 0 
    2 3 

можно объяснить очень просто

Сначала с помощью метода изменить размер

v.resize(2);

вы добавили два пустых std :: vector в вектор v.

Затем в цикле

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]);
}

вы изменили размер каждого из них. Итак, теперь v [0] и v [1]

0 0 
0 0 

И тогда вы получаете вычитание

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

После этого вектор v был добавлен с

    2 4 
   -1 0 
    2 3 

Ещё вопросы

Сообщество Overcoder
Наверх
Меню