Matlab: арифметическая операция над столбцами внутри цикла for (просто, но хитро!)

Я пытаюсь представить простую матрицу m*n (предположим, что она имеет только одну строку!), такую, что m1n1 = m1n1^1, m1n2 = m1n1^2, m1n3 = m1n1^3, m1n3 = m1n1^4, .. , m1ni = m1n1^i. Другими словами, я пытаюсь выполнить итерацию по столбцам матрицы n раз, чтобы добавить новый вектор (столбец) в конце, чтобы каждый из индексов имел то же значение, что и первый вектор, но возведен в степень его номера столбца. н.

Это исходный вектор:

v =
    1.2421
    2.3348
    0.1326
    2.3470
    6.7389
, а это v после третьей итерации:

v = 
    1.2421    1.5429    1.9165
    2.3348    5.4513   12.7277
    0.1326    0.0176    0.0023
    2.3470    5.5084   12.9282
    6.7389   45.4128  306.0329
теперь, учитывая, что я полный нуб в Matlab, я действительно недооценил сложность такой, казалось бы, простой задачи, которая заняла у меня почти день отладки и серфинга в Интернете, чтобы найти какую-либо подсказку. Вот что я придумал:

rows = 5;
columns = 3;
v = x(1:rows,1);
k = v;
Ncol = ones(rows,1);
extraK = ones(rows,1);

disp(v)

for c = 1:columns
    Ncol = k(:,length(k(1,:))).^c; % a verbose way of selecting the last column only.
    extraK = cat(2,extraK,Ncol);
end

k = cat(2,k,extraK);
disp(extraK(:,2:columns+1)) % to cut off the first column

теперь этот код (по какой-то странной причине) работает, только если строк = 6 или меньше, а столбцов = 3 или меньше.

when rows = 7, this is the output:

v = 1.0e+03 *

0.0012    0.0015    0.0019
0.0023    0.0055    0.0127
0.0001    0.0000    0.0000
0.0023    0.0055    0.0129
0.0067    0.0454    0.3060
0.0037    0.0138    0.0510
0.0119    0.1405    1.6654

Как я могу заставить его работать с любым количеством строк и столбцов?

Спасибо!


person 7kemZmani    schedule 01.02.2015    source источник
comment
Я попробую это bsxfun и вернусь к вам, если это помогло.   -  person 7kemZmani    schedule 01.02.2015
comment
на самом деле... Есть несоответствие между вашим определением и объявленными вами результатами! В вашем v с 3 столбцами каждый столбец кажется первым v в степени индекса столбца (поэтому 3-й столбец равен v.^3). Но в определении третий столбец должен быть ((v.^2).^3), то есть v.^6. Какой из них правильный?   -  person Hoki    schedule 01.02.2015
comment
да, вы правы, @Hoki возведение v в степень столбца n - это то, что я хочу. Я обновлю пост.   -  person 7kemZmani    schedule 01.02.2015
comment
@AbdulelahAl-Jeffery - хорошо. так что вы не хотите ссылаться на последний столбец? Вы просто хотите использовать исходный вектор и возвести его в n степень? Если это так, то то, что у меня было изначально, было правильным.   -  person rayryeng    schedule 01.02.2015
comment
Я все еще не могу заставить его работать, хотя! Я продолжаю получать вывод, который я видел снова и снова с тех пор, как начал отлаживать этот код.   -  person 7kemZmani    schedule 01.02.2015
comment
пример правильный, и я могу заверить вас, что полностью понимаю эту смехотворно простую проблему. Позвольте мне добавить еще несколько деталей из оригинальной работы, которую я сейчас делаю: я беру небольшой замещающий вектор v из большего вектора x и пытаюсь применить простую степенную операцию к каждому индексу v, как описано. Причина в том, что я получил неожиданные результаты, когда работал с x, и я решил уменьшить задачу до меньшего размера, чтобы я мог обдумать ее, и все сводилось к этой загадочной матрице 6 * 3 !!   -  person 7kemZmani    schedule 01.02.2015
comment
Тогда почему бы вам не привести пример того, что вы ожидаете получить в сравнении с тем, что вы получаете с помощью своего кода? Я не вижу этого в вашем описании проблемы, за исключением случаев, когда n=3. Покажите нам неудачный случай.   -  person rayryeng    schedule 01.02.2015
comment
хорошо, теперь мне кажется, код правильный, но что-то не так с форматом, вывод должен быть двойным! (хммм, может быть, кто-то сейчас что-то на кого-то натравит!!)   -  person 7kemZmani    schedule 01.02.2015
comment
Я изменил формат на банк, чтобы вы могли видеть значащие цифры. Введите format short, чтобы сбросить форматирование. Возможно, вам действительно следует прочитать код перед копированием и вставкой.   -  person rayryeng    schedule 01.02.2015
comment
На самом деле format longG было именно то, ради чего я потратил свой день впустую. Большое спасибо @rayryeng, да благословит тебя Бог, чувак, да благословит тебя Бог.   -  person 7kemZmani    schedule 01.02.2015
comment
Босс без проблем. Рад, что вы это исправили.   -  person rayryeng    schedule 01.02.2015


Ответы (2)


Я нашел несколько неправильных вещей в вашем коде:

  1. Я не уверен, почему вы определяете d = 3;. Это просто придирка, но вы можете безопасно удалить это из своего кода.
  2. Вы не выполняете операцию питания должным образом. В частности, посмотрите на это заявление:

    Ncol = k(:,length(k(1,:))).^c; % a verbose way of selecting the last column only.
    

    Вы выборочно выбираете последний столбец, и это здорово, но вы не применяете операцию питания должным образом. Насколько я понимаю ваше утверждение, вы хотите взять исходный вектор и выполнить операцию мощности в степени n, где n – текущая итерация. Поэтому вам действительно просто нужно сделать это:

    Ncol = k.^c;
    

    Как только вы замените Ncol строкой выше, код должен работать. Я также заметил, что вы вырезаете первый столбец своего результата. Причина, по которой вы получаете повторяющиеся столбцы, заключается в том, что ваш цикл for начинается с c = 1. Поскольку вы уже вычислили v.^1 = v, вы можете просто начать цикл с c = 2. Измените начальную точку цикла на c = 2, и вы сможете избавиться от удаления первого столбца.


Однако я собираюсь сделать это альтернативным способом в одной строке кода. Прежде чем мы это сделаем, давайте рассмотрим теорию того, что вы пытаетесь сделать.

Учитывая вектор v, который состоит из m элементов, хранящихся в векторе m x 1, вы хотите иметь матрицу размера m x n, где n — желаемое количество столбцов, и для каждого столбца, начиная слева направо, вы хотите взять v в nй степени.

Поэтому, учитывая ваш пример из вашей третьей «итерации», первый столбец представляет v, второй столбец представляет v.^2, а третий столбец представляет v.^3.


Я собираюсь познакомить вас с возможностями bsxfun. bsxfun обозначает функцию Binary Singleton EXpansion. Что делает bsxfun, так это то, что если у вас есть два входа, где один или оба входа имеют одноэлементное измерение, или если любой из обоих входов имеет только одно измерение со значением 1, каждый вход реплицируется в своем единственном элементе. размеры, чтобы соответствовать размеру других входных данных, а затем к этим входным данным применяется поэлементная операция для получения вашего вывода.

Например, если бы у нас было два таких вектора:

A = [1 2 3]

B = [1
     2
     3]

Обратите внимание, что один из них — вектор-строка, а другой — вектор-столбец. bsxfun увидит, что A и B имеют одноэлементные измерения, где A имеет одноэлементное измерение, представляющее собой количество строк, равное 1, а B имеет одноэлементное измерение, которое представляет собой количество столбцов, равное 1. Следовательно, мы будем дублировать B столько столбцов. так как есть в A и дублируем A для такого количества строк, сколько есть в B, и мы на самом деле получаем:

A = [1 2 3
     1 2 3
     1 2 3]

B = [1 1 1
     2 2 2
     3 3 3]

Когда у нас есть эти две матрицы, вы можете применить к этим матрицам любые поэлементные операции, чтобы получить результат. Например, вы можете складывать, вычитать, возводить в степень или выполнять поэлементное умножение или деление.


Теперь, как этот сценарий применим к вашей проблеме, заключается в следующем. Что вы делаете, так это то, что у вас есть вектор v, и у вас будет матрица полномочий, например:

M = [1 2 3 ... n
     1 2 3 ... n
     ...........
     ...........
     1 2 3 ... n]

По сути, у нас будет столбец из 1, за которым следует столбец из 2, до любого количества столбцов, которое вы хотите n. Мы применили бы bsxfun к вектору v, который является вектором-столбцом, и к другому вектору, который представляет собой всего лишь одну строку значений от 1 до n. Вы бы применили силовую операцию для достижения результата. Таким образом, вы можете удобно рассчитать свой результат, выполнив:

columns = 3;
out = bsxfun(@power, v, 1:columns);

Давайте попробуем несколько примеров с вашим вектором v:

>> v = [1.2421; 2.3348; 0.1326; 2.3470; 6.7389];
>> columns = 3;
>> out = bsxfun(@power, v, 1:columns)

out =

    1.2421    1.5428    1.9163
    2.3348    5.4513   12.7277
    0.1326    0.0176    0.0023
    2.3470    5.5084   12.9282
    6.7389   45.4128  306.0321

>> columns = 7;
>> format bank
>> out = bsxfun(@power, v, 1:columns)

out =

  Columns 1 through 5

          1.24          1.54          1.92          2.38          2.96
          2.33          5.45         12.73         29.72         69.38
          0.13          0.02          0.00          0.00          0.00
          2.35          5.51         12.93         30.34         71.21
          6.74         45.41        306.03       2062.32      13897.77

  Columns 6 through 7

          3.67          4.56
        161.99        378.22
          0.00          0.00
        167.14        392.28
      93655.67     631136.19

Обратите внимание, что при установке столбцов на 3 мы получаем то, что видим в вашем посте. Чтобы увеличить столбцы до 7, мне пришлось изменить способ представления чисел, чтобы вы могли четко видеть числа. Если этого не сделать, это приведет к экспоненциальной форме, а после значащих цифр будет много нулей.


Удачи!

person rayryeng    schedule 01.02.2015
comment
чувак, ты так быстро печатаешь ... Я готовил точно такой же ответ (даже с меньшими объяснениями), и к тому времени, когда я закончил, я вижу, что твой ответ существует уже много лет назад !! в любом случае молодец. - person Hoki; 01.02.2015
comment
да, вы правы, я должен был объяснить, что такое v = x(1:rows,1);, но тем не менее значение v указано в примере, который я приводил ранее. Также вы правы в том, что d = 3; это просто опечатка, так как я на самом деле просто сократил свой исходный код до этого примера кода, который отражает именно мою проблему. Это был долгий день, чувак! - person 7kemZmani; 01.02.2015
comment
Ну, очевидно, функция bsxfun имеет ту же изначальную проблему, что она ломается, если количество строк больше 6 или количество столбцов больше 3!!! также ваша версия моего кода, похоже, имеет ту же проблему. Ничего кроме матрицы 6х3!!! - person 7kemZmani; 01.02.2015

При вычислении кумулятивных мощностей можно повторно использовать предыдущие результаты: для скалярных x и n x.^n равно x * x.^(n-1), где x.^(n-1) уже получено. Это может быть более эффективно, чем независимое вычисление каждой степени, потому что умножение происходит быстрее, чем мощность.

Пусть N будет максимальным желаемым показателем степени. Чтобы использовать описанный подход, вектор-столбец v повторяется N раз по горизонтали (repmat), а затем к каждой строке применяется кумулятивный продукт (cumprod):

v =[1.2421; 2.3348; 0.1326; 2.3470; 6.7389]; %// data. Column vector
N = 3; %// maximum exponent
result = cumprod(repmat(v, 1, N), 2);
person Luis Mendo    schedule 01.02.2015
comment
Это удобная практика, я постараюсь использовать в будущем. Спасибо! - person 7kemZmani; 01.02.2015