(Я отвечу, несмотря на то, что это домашняя работа. Я думаю, что многие не понимают, почему был создан bsxfun.)
Есть и другие решения по умножению. Типичными являются использование repmat, цикл или умножение на диагональную матрицу. Лучше, если диагональная матрица сделана разреженной матрицей. Тем не менее, bsxfun определенно является правильным решением. Он был написан для решения подобных проблем. Проблема в том, что когда вы делаете такие вещи, как
A = magic(3) + 5
MATLAB понимает, что он должен добавить 5 к каждому элементу магии (3). Точно так же, когда вы делаете
A = magic(4).*2
Опять же, MATLAB понимает, что умножение должно быть распространено на все элементы. По сути, MATLAB неявно расширяет скаляр в массив того же размера, что и его партнер по сложению или умножению, а затем выполняет операцию. Это то, что было явно сделано решателем repmat.
Проблема с явным скалярным расширением состоит в том, что для этого расширения требуются время и память. Поэтому времена и плюсы достаточно умны, чтобы признать, что скалярное расширение подходит, но на самом деле не выполняют явную операцию захвата памяти. MATLAB не знает, что делать при попытке
A = magic(3).*rand(1,3)
В прошлом решением было использовать repmat. Но когда вы используете repmat для явного расширения вектора в матрицу, вы съедаете много памяти, чтобы решить проблему векторизованным способом. Да, для векторизации характерно обменять память на время в MATLAB, но это может быть плохо, если вы уже ограничены в памяти и работаете над большой проблемой. Заставлять MATLAB (и вашу ОС) перемещаться в виртуальную память - очень плохая идея, когда в этом нет необходимости. (Любое решение приемлемо для крошечной проблемы.)
Итак, когда вы пытаетесь умножить массив типа magic (3) на строку или вектор столбца, должен ли MATLAB понять, что он должен выполнять неявное расширение вектора в массив? Или MATLAB должен предположить, что вы сделали ошибку, и пометить это как таковой? Эта проблема, известная как расширение одноэлементных измерений, является проблемой. (Одноэлементное измерение находится в векторе, где одно из измерений было 1.) Возвращение сообщения об ошибке является хорошей идеей для многих пользователей, поскольку часто это сигнализирует о том, что ошибка найдена, ошибка допущена. Простое автоматическое расширение всех одноэлементных измерений для решения рассматриваемой проблемы может показаться опасным. На самом деле, было много дискуссий о том, что делать. Например, должен ли MATLAB создать предпочтение, в котором пользователь мог бы разрешить расширение одноэлементных измерений в своей версии MATLAB? Это было бы плохой идеей, так как это сделало бы код непереносимым между системами.
Кроме того, если бы базовые операторы MATLAB были изменены, чтобы всегда расширять все одноэлементные измерения, то код MATLAB был бы сильно непереносимым к более старым версиям.
Мы даже обсуждали создание целого нового набора операторов MATLAB, таких как. *, Параллельно с *, для выполнения операции при расширении одноэлементных измерений. Это тоже была плохая идея, и ее по праву избегали.
Решением было создание BSXFUN (Binary Scalar eXpansion FUNction), чтобы эта операция могла быть выполнена эффективно, когда это необходимо. В файлообменнике обнаружен bsxfun, который позволяет пользователям старых версий получить такое поведение, поэтому переносимость поддерживается как можно лучше. BSXFUN позволяет работать с любой парой аргументов, применяя пользовательскую функцию между ними. Так что это позволяет вам делать такие вещи:
A = rand(5,1);
B = rand(1,3);
C = bsxfun(@plus,A,B);
для создания матрицы 5x3 суммы элементов в каждом из A и B. Вы также можете использовать любую функцию в качестве первого операнда, поэтому BSXFUN очень мощный.
Наконец, еще один способ взглянуть на BSXFUN - это вариация внешнего продукта. Таким образом, эта операция в MATLAB прекрасно определена:
A = rand(5,1);
B = rand(1,3);
C = A*B;
Однако, любая из этих операций
D = A-B;
E = A^B;
приведет к ошибке. BSXFUN позволяет вам делать их эффективно, не занимая объем памяти при расширении синглтона.
D = bsxfun(@minus,A,B);
E = bsxfun(@power,A,B);