Matlab: как выборочно присвоить значения матрице

У меня есть 3 матрицы x, y и z порядка 3*3. Я хочу создать новую матрицу k со значением = 1./(x.^2+y.^2+z.^2), если (x.^2+y.^2+z.^2 > 1) и значение = 0 в противном случае. Я пытаюсь использовать это:

  k(x.^2+y.^2+z.^2>1)= 1./(x.^2+y.^2+z.^2)

но выдает ошибку: в присваивании A(I) = B количество элементов в B и I должно быть одинаковым. Может ли кто-нибудь предоставить простое решение в одной строке, где мне не нужно использовать циклы for


person Bosnia    schedule 16.03.2014    source источник
comment
Если (x.^2+y.^2+z.^2 › 1) для любого из x, y'x и z или всех x, y и z? Если условие не выполняется, должны ли все 9 значений в z стать 0?   -  person Divakar    schedule 16.03.2014
comment
нам вообще не нужно менять z. мы должны поэлементно проверить значение x.^2+y.^2+z.^2   -  person Bosnia    schedule 16.03.2014
comment
В части условия вы сравниваете 9 значений с 1. Итак, мой вопрос был в том, как вы хотите сравнивать? Должны ли all 9 значений быть больше 1 или any из 9 значений должны быть больше 1?   -  person Divakar    schedule 16.03.2014


Ответы (3)


Я не уверен, почему вы хотите сделать это, а не разделить его на две операции. Таким образом, вы экономите на вычислении суммы квадратов дважды.

x = rand(3,3);
y = rand(3,3);
z = rand(3,3);
k = 1./(x.^2+y.^2+z.^2);
k(k>1)=0;

В любом случае, другой способ сделать это — использовать принципы функционального программирования:

x = rand(3,3);
y = rand(3,3);
z = rand(3,3);
myfun = @(x,y,z) 1/(x^2+y^2+z^2) * (x^2+y^2+z^2>1);
k = arrayfun(myfun, x, y, z);

В качестве альтернативы вы можете смешать все в одну строку как:

k = arrayfun(@(x,y,z) 1/(x^2+y^2+z^2) * (x^2+y^2+z^2>1), x, y, z);

Что делает этот код, так это сопоставляет функцию myfun с каждым из элементов данных. Функция myfun довольно проста. Он вычисляет необходимое количество, но умножает его на условие привязки. Однако вы можете остерегаться< /а>.


РЕДАКТИРОВАТЬ: Чтобы ответить на комментарий. Если вы вообще не хотите вычислять количество, мы можем использовать условные анонимные функции. Для получения более подробной информации вы можете обратиться к это руководство.

iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
myfun = @(x,y,z) iif( x^2+y^2+z^2 <= 1, @() 0, x^2+y^2+z^2>1 ,@() 1/(x^2+y^2+z^2));
k = arrayfun(myfun, x, y, z);
person Nitish    schedule 16.03.2014
comment
на самом деле я просто хотел, чтобы Matlab не вычислял значение 1./(x.^2+y.^2+z.^2) для тех элементов, которым должно быть присвоено нулевое значение. Можете ли вы соответствующим образом изменить, чтобы настроить это? - person Bosnia; 16.03.2014
comment
@Bosnia, я отредактировал ответ. Используя новый фрагмент кода, вы не будете вычислять количество, если нужно присвоить 0. - person Nitish; 16.03.2014

Как насчет

k = x.^2+y.^2+z.^2;
k(k < 1) = 0;
k(k~= 0) = 1 ./ k(k~=0);
person Ben Voigt    schedule 16.03.2014

Если вы пытаетесь сэкономить некоторое время обработки (т.е. вообще не вычислять сумму квадратов для тех случаев, когда она меньше единицы), то практически единственным решением является поиск в таблице. В противном случае должен работать следующий код.

k=1./(x.^2+y.^2+z.^2)
k(k<=1)=0

вы можете сократить время (при условии, что x, y и z могут быть больше 1)

idx0=x<1 & y<1 & z<1
k=zeros(3)
k(idx0)=1./(x(idx0).^2+y(idx0).^2+z(idx0)^2)
k(k<=1)=0

Ваше оригинальное решение будет работать, если вы измените его, чтобы использовать индексатор (я не профилировал его, но я уверен, что это займет больше времени, чем мое :))

idx0=x.^2+y.^2+z.^2>1
k=zeros(3)
k(idx0)=1./(x(idx0).^2+y(idx0).^2+z(idx0)^2)
person Alex Lizz    schedule 16.03.2014
comment
Я пытаюсь сэкономить на вычислении 1./(x.^2+y.^2+z.^2) для тех элементов, которым должен быть присвоен ноль. (На самом деле это сложная функция от 1./(x.^2+y.^2+z.^2), поэтому вычисление займет много времени) - person Bosnia; 16.03.2014
comment
В вашем исходном примере, который можно изменить для работы, сумма квадратов будет вычисляться более одного раза для каждого элемента (один в условном выражении и один для тех случаев, которые соответствуют условному выражению). Мой спасает как минимум со второго раза. В любом случае, какой тип и диапазон значений для x, y, z и какая точность результата вам нужна? - person Alex Lizz; 16.03.2014
comment
введите double x,y,z от 0 до 5.038 - person Bosnia; 16.03.2014