Угловые ящики, неожиданные и необычные MATLAB

28

На протяжении многих лет, читая другие коды, я встречался и собирал некоторые примеры синтаксиса 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([])

Сюрпризно any([]) возвращает false и all([]) возвращает true. И я всегда думал, что all сильнее, чем any.

EDIT:

с непустым аргументом 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(:), в этом случае аргумент ввода функции передается как char двоеточие ':'.

Например, пусть Bar.Foo = @(x) disp(x) Теперь вызов Bar.Foo(:) печатает char ':' в командном окне MATLAB.

Эта странная функция работает со всеми версиями MATLAB 7 без предупреждений.


a = {'aa', 'bb'
'cc', 'dd'};

Сюрпризально этот код не возвращает вектор и не вызывает ошибку, а определяет матрицу, используя только макет кода. Это, вероятно, реликт с древних времен.

EDIT: очень удобная функция, см. комментарий gnovice.


set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'})

Этот код делает то, что вы, вероятно, ожидаете от него. Эта функция set принимает структуру, поскольку ее второй аргумент является известным фактом и имеет смысл, и этот синтакс является всего лишь cell2struct.


Правила равноценности иногда являются неожиданными. Например, 'A'==65 возвращает true (хотя для C-специалистов это само собой разумеется). Аналогично isequal([],{}) retuns, как и ожидалось, false и isequal([],'') возвращает true.

Строковая-числовая эквивалентность означает, что все строковые функции могут использоваться также для числовых массивов, например, для поиска индексов под-массива в большом массиве:

ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] )

Функция MATLAB isnumeric() возвращает false для booleans. Это просто... false: -)


О каких дополнительных неожиданных/необычных функциях MATLAB вы знаете?

  • 1
    Я полагаю, что в этом случае Wiki сообщества оправдано, так как это в основном вопрос для составления списка.
  • 1
    @gnovice: изменено на вики сообщества
Показать ещё 6 комментариев
Теги:

3 ответа

12

Координаты изображения и координаты участка Используется для получения меня каждый раз.

%# 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 run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it not in the right place

%# plot a green circle with x,y switched, and it works
plot(y,x,'og')

Изменить 1

Размеры массива

Переменные имеют как минимум два измерения. Scalaры имеют размер [1,1], векторы - это размер [1,n] или [n,1]. Таким образом, ndims возвращает 2 для любого из них (фактически, ndims([]) равно 2, так как size([]) есть [0,0]). Это делает его немного громоздким, чтобы проверить размерность вашего ввода. Чтобы проверить наличие 1D массивов, вам нужно использовать 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
8

Вместо того, чтобы перечислять примеры странного синтаксиса MATLAB, я рассмотрю некоторые примеры в вопросе, который, по моему мнению, имеет смысл или ожидается/документирован/желателен.

  • Как ANY и ALL обрабатывать пустые аргументы:

    Результат 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 и т.д.) самый левый матричный элемент определяет тип результата.

  • Несколько строк без использования оператор продолжения строки (...):

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

    a = {'aa', 'bb'
    'cc', 'dd'};
    
    a = {'aa', 'bb'; ...
    'cc', 'dd'};
    
    a = {'aa', 'bb'; 'cc', 'dd'};
    

    Почему вы хотите, чтобы MATLAB вел себя так? Одна из причин, по которой я заметил, заключается в том, что он позволяет легко вырезать и вставлять данные из, например, документа Excel в переменную в командном окне MATLAB. Попробуйте следующее:

    • Выберите регион в файле Excel и скопируйте его.
    • Введите a = [ в MATLAB без возврата.
    • Щелкните правой кнопкой мыши в окне команд MATLAB и выберите "Вставить".
    • Введите ]; и нажмите return. Теперь у вас есть переменная a, которая содержит данные из строк и столбцов, которые вы выбрали в файле Excel, и которая поддерживает "форму" данных.
  • 1
    Я думаю, что это помогает указать, почему «все ([])» смущает людей - это потому, что «все» работает по-разному в повседневном языке, чем в логике / программировании. Я разместил пример в качестве комментария к вопросу.
  • 0
    По крайней мере, конкатенация в отличие от целых чисел выдает ошибку (r2010a)
5

Массивы против ячеек

Давайте рассмотрим базовый синтаксис для начала. Чтобы создать массив с элементами 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.

Все это не очень красивая ИМО.

  • 6
    Поведение ячейки на самом деле довольно непротиворечиво: arr (i) возвращает i-й элемент массива. В случае числового массива i-й элемент является числовым скаляром, в случае массива ячеек i-й является скалярной ячейкой, в случае массива структуры i-й является скалярной структурой. Фигурные скобки используются для «копания» в ячейке, как имена полей используются для «копания» в структуре. Также, как и для структур, вы можете перейти к элементам содержимого ячейки, таким как cellArray {i} (1,2)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню