Угловые шкафы, неожиданные и необычные MATLAB
На протяжении многих лет, читая чужой код, я столкнулся и собрал несколько примеров синтаксиса MATLAB, который может быть поначалу необычным и нелогичным. Пожалуйста, не стесняйтесь комментировать или дополнять этот список. Я проверил это с r2006a.
MATLAB всегда возвращает первый выходной аргумент функции (если он имеет хотя бы один) в рабочее пространство вызывающей стороны, также неожиданно, если функция вызывается без возврата таких аргументов, как myFunc1(); myFunc2();
рабочая область вызывающего абонента все еще будет содержать первый вывод myFunc2();
как "невидимый" ans
переменная. Это может сыграть важную роль, если ans
является эталонным объектом - он останется живым.
set([], 'Background:Color','red')
MATLAB иногда очень прощающий. В этом случае установка свойств для массива объектов работает также с бессмысленными свойствами, по крайней мере, когда массив пуст. Такие массивы обычно приходят из harray = findobj(0,'Tag','NotExistingTag')
myArray([1,round(end/2)])
Это использование end
Ключевое слово может показаться нечистым, но иногда очень удобно вместо length(myArray)
,
any([]) ~= all([])
Surprisigly any([])
возвращается false
а также all([])
возвращается true
, И я всегда думал, что all
сильнее any
,
РЕДАКТИРОВАТЬ:
с не пустым аргументом all()
возвращается true
для подмножества значений, для которых any()
возвращается true
(например, таблица истинности). Это означает, что any()
false
подразумевает all()
false
, Это простое правило нарушается MATLAB с []
в качестве аргумента.
Лорен также написал об этом в блоге.
Select(Range(ExcelComObj))
Процедура отправки COM-объекта в стиле процедур. Не удивляйся что exist('Select')
возвращает ноль!
[myString, myCell]
В этом случае MATLAB делает неявное приведение строковой переменной myString
на тип клетки {myString}
, Это работает, даже если я не ожидал, что это так.
[double(1.8), uint8(123)] => 2 123
Еще один пример. Все, вероятно, ожидают uint8
значение приведено к double
но у Mathworks есть другое мнение. Без предупреждения это поведение очень опасно.
a = 5;
b = a();
Это выглядит глупо, но вы можете вызвать переменную в круглых скобках. На самом деле это имеет смысл, потому что таким образом вы можете выполнить функцию, учитывая ее дескриптор.
Синтаксис Foo(:)
работает не только с данными, но и с функциями, если они называются Bar.Foo(:)
в этом сценарии входной аргумент функции передается как двоеточие ':'
,
Например пусть Bar.Foo = @(x) disp(x)
Сейчас звоню Bar.Foo(:)
печатает чар ':'
в командном окне MATLAB.
Эта странная функция работает со всеми версиями MATLAB 7 без предупреждений.
a = {'aa', 'bb'
'cc', 'dd'};
Удивительно, но этот код не возвращает вектор и не вызывает ошибку, а определяет матрицу, используя только компоновку кода. Это, вероятно, реликт с древних времен.
РЕДАКТИРОВАТЬ: очень удобная функция, см. Комментарий от gnovice.
set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})
Этот код делает то, что вы, вероятно, ожидаете. Эта функция set
принимает структуру, поскольку ее второй аргумент является известным фактом и имеет смысл, а этот синтаксис является просто cell2struct
далеко.
Правила эквивалентности поначалу иногда бывают неожиданными. Например 'A'==65
возвращает true (хотя для C-специалистов это очевидно). так же isequal([],{})
повторы, как и ожидалось, false
а также isequal([],'')
возвращается true
,
Строково-числовая эквивалентность означает, что все строковые функции можно использовать также для числовых массивов, например, для поиска индексов подмассива в большом массиве:
ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )
Функция MATLAB isnumeric()
возвращается false
для логических значений. Это кажется просто... ложным:-)
О каких еще неожиданных / необычных функциях MATLAB вам известно?
3 ответа
Координаты изображения против координат графика Используется, чтобы получить меня каждый раз.
%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;
%# show the image
figure
imshow(img);
%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place
%# plot a green circle with x,y switched, and it works
plot(y,x,'og')
Редактировать 1
Размеры массива
Переменные имеют как минимум два измерения. Скаляры размерные [1,1]
, векторы размером [1,n]
или же [n,1]
, Таким образом, ndims
возвращает 2 для любого из них (на самом деле, ndims([])
2, так как size([])
является [0,0]
). Это немного затрудняет проверку на размерность вашего ввода. Чтобы проверить одномерные массивы, вы должны использовать isvector
, Нужны массивы 0D isscalar
,
Редактировать 2
Массив назначений
Обычно Matlab строго присваивает массивы. Например
m = magic(3);
m(1:2,1:3) = zeros(3,2);
бросает
??? Subscripted assignment dimension mismatch.
Тем не менее, эти работы:
m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'
Редактировать 3
Логическая индексация с массивами неправильного размера Удачи в отладке!
Логическая индексация, кажется, призывает find
, поскольку вашему логическому массиву не нужно столько же элементов, сколько есть индексов!
>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
1 1 0 1 0
>> m(id,:) %# id has five elements, m only four rows
ans =
16 2 3 13
5 11 10 8
4 14 15 1
%# this wouldn't work if the last element of id was 1, btw
>> id = logical([1 1 0])
id =
1 1 0
>> m(id,:) %# id has three elements, m has four rows
ans =
16 2 3 13
5 11 10 8
Вместо того, чтобы перечислять примеры странного синтаксиса MATLAB, я рассмотрю некоторые примеры в вопросе, которые, на мой взгляд, имеют смысл или являются ожидаемым / задокументированным / желаемым поведением.
Как ЛЮБЫЕ и ВСЕ обрабатывают пустые аргументы:
Результат
any([])
имеет смысл: во входном векторе нет ненулевых элементов (поскольку он пуст), поэтому он возвращает false.Результат
all([])
лучше понять, подумав о том, как реализовать свою версию этой функции:function allAreTrue = my_all(inArray) allAreTrue = true; N = numel(inArray); index = 1; while allAreTrue && (index <= N) allAreTrue = (inArray(index) ~= 0); index = index + 1; end end
Эта функция перебирает элементы
inArray
пока он не встретит тот, который равен нулю. ЕслиinArray
пусто, цикл никогда не вводится и значение по умолчаниюallAreTrue
возвращаетсяОбъединение в отличие от классов:
При объединении разных типов в один массив MATLAB следует заданному приоритету классов и соответствующим образом преобразует значения. Общий порядок приоритетов (от высшего к низшему):
char
,integer
(любого знака или количества бит),single
,double
, а такжеlogical
, Вот почему[double(1.8), uint8(123)]
дает вам результат типаuint8
, При объединении в отличие от целочисленных типов (uint8
,int32
и т. д.), крайний левый матричный элемент определяет тип результата.Несколько строк без использования оператора продолжения строки (
...
):При построении матрицы с несколькими строками вы можете просто нажать клавишу возврата после ввода одной строки и ввести следующую строку на следующей строке, не используя точку с запятой для определения новой строки или
...
продолжить линию. Следовательно, следующие объявления эквивалентны:a = {'aa', 'bb' 'cc', 'dd'}; a = {'aa', 'bb'; ... 'cc', 'dd'}; a = {'aa', 'bb'; 'cc', 'dd'};
Почему вы хотите, чтобы MATLAB вел себя так? Одна из причин, которую я заметил, заключается в том, что это позволяет легко вырезать и вставлять данные, например, из документа Excel в переменную в командном окне MATLAB. Попробуйте следующее:
- Выберите регион в файле Excel и скопируйте его.
- Тип
a = [
в MATLAB, не нажимая возврата. - Щелкните правой кнопкой мыши командное окно MATLAB и выберите "Вставить".
- Тип
];
и ударил в ответ. Теперь у вас есть переменнаяa
который содержит данные из строк и столбцов, выбранных вами в файле Excel, и который поддерживает "форму" данных.
Массивы против клеток
Давайте посмотрим на некоторый основной синтаксис для начала. Для создания массива с элементами a, b, c вы пишете [a b c]
, Чтобы создать ячейку с массивами A, B, C, вы пишете {A B C}
, Все идет нормально.
Доступ к элементам массива осуществляется следующим образом: arr(i)
, Для клеток это cell{i}
, Все еще хорош.
Теперь давайте попробуем удалить элемент. Для массивов: arr(i) = []
, Экстраполируя приведенные выше примеры, вы можете попробовать cell{i} = {}
для ячеек, но это синтаксическая ошибка. Правильный синтаксис для удаления элемента ячейки, по сути, тот же самый синтаксис, который вы используете для массивов: cell(i) = []
,
Таким образом, большую часть времени вы обращаетесь к ячейкам, используя специальный синтаксис, но при удалении элементов вы используете синтаксис массива.
Если вы покопаетесь глубже, вы обнаружите, что на самом деле ячейка - это массив, в котором каждое значение имеет определенный тип. Так что вы все еще можете написать cell(i)
, вы просто получите {A}
(однозначная ячейка!) назад. cell{i}
это сокращение, чтобы получить A
непосредственно.
Все это не очень симпатичное ИМО.