Я делаю очень базовую линейную алгебру, и я, вероятно, вообще не вижу смысла здесь.
Скажем, у меня есть следующие матрицы:
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 значения.
Мне, наверное, не хватает чего-то глупого.
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
2 4
тогда как мне нужна еще одна матрица с еще 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]);
}
Этот цикл работает с двумя элементами 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
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
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
std::vector
имеет ужасный интерфейс для линейной алгебры. Конкретная проблема, с которой вы столкнулись, заключается в том, что вы путаете размеры и положения элементов.