Поиск…


Не называйте переменную с именем существующей функции

Уже существует функция sum() . В результате, если мы будем называть переменную с тем же именем

sum = 1+3;

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

A = rand(2);
sum(A,1)

мы получим загадочную ошибку :

Subscript indices must either be real positive integers or logicals.

сначала clear() переменную, а затем используйте функцию

clear sum

sum(A,1)
ans =
       1.0826       1.0279

Как мы можем проверить, существует ли функция, чтобы избежать этого конфликта?

Используйте which() с флагом -all :

which sum -all
sum is a variable.
built-in (C:\Program Files\MATLAB\R2016a\toolbox\matlab\datafun\@double\sum)   % Shadowed double method
...

Этот вывод говорит нам, что sum является первой переменной и что следующие методы (функции) затенены ею, то есть MATLAB сначала попытается применить наш синтаксис к переменной, а не использовать этот метод.

То, что вы видите, НЕ является тем, что вы получаете: char vs cellstring в окне команд

Это основной пример, нацеленный на новых пользователей. Он не фокусируется на объяснении разницы между char и cellstring .


Может случиться так, что вы хотите избавиться от ' в ваших строках», хотя вы никогда их не добавляли. Фактически, это артефакты, которые используется в командном окне для различения некоторых типов.

Строка будет печатать

s = 'dsadasd'
s =
dsadasd

Ячейка будет печатать

c = {'dsadasd'};
c = 
    'dsadasd'

Обратите внимание, что одиночные кавычки и отступы являются артефактами, чтобы уведомить нас о том, что c - это cellstring а не char . Строка фактически содержится в ячейке, т. Е.

c{1}
ans =
dsadasd

Операторы транспонирования

  • .' является правильным способом транспонировать вектор или матрицу в MATLAB.
  • ' - правильный способ взять комплексно-сопряженную транспозицию (ака эрмитово сопряженную) вектора или матрицы в MATLAB.

Обратите внимание, что для транспонирования .' , перед апострофом существует период . Это согласуется с синтаксисом для других элементарных операций в MATLAB: * умножает матрицы , .* умножает элементы матриц вместе. Обе команды очень похожи, но концептуально очень разные. Как и другие команды MATLAB, эти операторы являются «синтаксическим сахаром», который во время выполнения превращается в «правильный» вызов функции. Подобно тому, как == становится оценкой функции eq , подумайте .' как сокращенное обозначение для transpose . Если бы вы только пишете ' (без точки), вы фактически используете команду ctranspose , которая вычисляет сложную сопряженную транспозицию , которая также известна как эрмитова сопряженная , часто используемая в физике. Пока транспонированный вектор или матрица вещественны, оба оператора производят одинаковый результат. Но как только мы будем заниматься сложными числами , мы неизбежно столкнемся с проблемами, если не будем использовать «правильную» стенографию. Что «правильно» зависит от вашего приложения.

Рассмотрим следующий пример матрицы C содержащей комплексные числа:

>> C = [1i, 2; 3*1i, 4]
C =
   0.0000 + 1.0000i   2.0000 + 0.0000i
   0.0000 + 3.0000i   4.0000 + 0.0000i

Возьмем транспонирование, используя сокращенное выражение .' (с периодом). Выход такой, как ожидалось, транспонированная форма C

>> C.'
ans =
   0.0000 + 1.0000i   0.0000 + 3.0000i
   2.0000 + 0.0000i   4.0000 + 0.0000i

Теперь давайте использовать ' (без периода). Мы видим, что в дополнение к транспозиции комплексные значения также трансформируются в их комплексные сопряжения .

>> C'
ans =
   0.0000 - 1.0000i   0.0000 - 3.0000i
   2.0000 + 0.0000i   4.0000 + 0.0000i

Подводя итог, если вы намереваетесь рассчитать эрмитовское сопряженное, комплексно-сопряженное транспонирование, то используйте ' (без периода). Если вы просто хотите вычислить транспонирование без комплексного сопряжения значений, используйте .' (с периодом).

Неопределенная функция или метод X для входных аргументов типа Y

Это длинный способ MATLAB сказать, что он не может найти функцию, которую вы пытаетесь вызвать. Существует несколько причин, по которым вы можете получить эту ошибку:

Эта функция была введена после вашей текущей версии MATLAB

Онлайн-документация MATLAB обеспечивает очень приятную функцию, которая позволяет вам определить, в какой версии была введена данная функция. Он расположен в левом нижнем углу каждой страницы документации:

введите описание изображения здесь

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

У вас нет этого инструментария!

Базовая установка MATLAB имеет большое количество функций; однако более специализированные функциональные возможности упакованы в панели инструментов и продаются отдельно Mathworks. Документация для всех панелей инструментов видна, есть ли у вас панель инструментов или нет, поэтому обязательно проверьте и посмотрите, есть ли у вас соответствующий набор инструментов.

Чтобы проверить, к какой панели инструментов принадлежит данная функция, посмотрите в левом верхнем углу интерактивной документации, чтобы узнать, указан ли конкретный набор инструментов.

введите описание изображения здесь

Затем вы можете определить, какие панели инструментов установлены вашей версией MATLAB, выпустив команду ver которая выведет список всех установленных наборов инструментов.

Если у вас нет установленного набора инструментов и вы хотите использовать эту функцию, вам нужно будет приобрести лицензию для этого конкретного инструментария из The Mathworks.

MATLAB не может найти функцию

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

Помните о неточности с плавающей запятой

Числа с плавающей запятой не могут представлять все действительные числа. Это известно как неточность с плавающей запятой.

Существует бесконечно много чисел с плавающей запятой, и они могут быть бесконечно длинными (например, π ), поэтому возможность их представления идеально потребует бесконечного количества памяти. Увидев это, возникла проблема, было разработано специальное представление для хранения «реального числа» в компьютере, стандарт IEEE 754 . Короче говоря, он описывает, как компьютеры хранят этот тип чисел с показателем и мантиссой,

floatnum = sign * 2^exponent * mantissa

При ограниченном количестве бит для каждого из них может быть достигнута только конечная точность. Чем меньше число, тем меньше разрыв между возможными числами (и наоборот!). Вы можете попробовать свои реальные цифры в этом онлайн-демо .

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

Примеры: сравнение плавающих точек WRONG:

>> 0.1 + 0.1 + 0.1  == 0.3

ans =

  logical

   0

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

Ниже приведен еще один пример, где число с плавающей запятой используется как условие остановки в цикле while: **

k = 0.1;
while k <= 0.3 
  disp(num2str(k));
  k = k + 0.1;
end

% --- Output: ---
0.1
0.2

Он пропускает последний ожидаемый цикл ( 0.3 <= 0.3 ).

Пример: Выполнено сравнение с плавающей запятой. RIGHT:

x = 0.1 + 0.1 + 0.1;
y = 0.3;
tolerance = 1e-10; % A "good enough" tolerance for this case.

if ( abs( x - y ) <= tolerance )
  disp('x == y');
else
  disp('x ~= y');
end

% --- Output: ---
x == y

Несколько замечаний:

  • Как и ожидалось, теперь x и y рассматриваются как эквивалентные.
  • В приведенном выше примере выбор допуска выполнялся произвольно. Таким образом, выбранное значение может не подходить для всех случаев (особенно при работе с гораздо меньшими номерами). Выбор метода разумно может быть выполнен с использованием функции eps , т. N*eps(max(x,y)) , где N - некоторое конкретное заданное число. Разумным выбором для N , который также является достаточно разрешительным, является 1E2 (хотя в приведенной выше проблеме N=1 также будет достаточно).

Дальнейшее чтение:

См. Эти вопросы для получения дополнительной информации о неточности с плавающей запятой:

Недостаточно входных аргументов

Часто начинающие разработчики MATLAB будут использовать редактор MATLAB для написания и редактирования кода, в частности пользовательских функций с входами и выходами. В верхней части есть кнопка « Выполнить» , которая доступна в последних версиях MATLAB:

введите описание изображения здесь

Как только разработчик заканчивается кодом, они часто испытывают желание нажать кнопку « Запустить» . Для некоторых функций это будет работать нормально, но для других они получат ошибку Недопустимые Not enough input arguments и будут озадачены тем, почему возникает ошибка.

Причина, по которой эта ошибка может не произойти, заключается в том, что вы написали сценарий MATLAB или функцию, которая не принимает входных аргументов. С помощью кнопки Run запускается тестовый скрипт или запускается функция, не принимающая входных аргументов. Если для вашей функции требуются входные аргументы, ошибка « Not enough input arguments будет возникать, поскольку вы написали функции, которые ожидают ввода входных данных внутри функции. Поэтому вы не можете ожидать, что функция будет работать, просто нажав кнопку « Выполнить» .

Чтобы продемонстрировать эту проблему, предположим, что у нас есть функция mult которая просто умножает две матрицы вместе:

function C = mult(A, B)
    C = A * B;
end

В последних версиях MATLAB, если вы написали эту функцию и нажали кнопку « Запустить» , она даст вам ожидаемую ошибку:

>> mult
Not enough input arguments.

Error in mult (line 2)
    C = A * B;

Существует два способа решить эту проблему:

Метод №1 - с помощью командной строки

Просто создайте нужные вам данные в командной строке, затем запустите функцию, используя созданные вами входы:

A = rand(5,5);
B = rand(5,5);
C = mult(A,B);

Метод № 2 - Интерактивно через редактор

Под кнопкой « Выполнить» находится темная черная стрелка. Если вы нажмете на эту стрелку, вы можете указать переменные, которые хотите получить из рабочего пространства MATLAB, набрав способ, которым вы хотите вызвать функцию, точно так же, как вы видели в методе # 1. Убедитесь, что переменные, которые вы указываете внутри функции, существуют в рабочей области MATLAB:

Следите за изменениями размера массива

Некоторые общие операции в MATLAB, такие как дифференциация или интеграция , выводят результаты, которые имеют различное количество элементов, чем входные данные. Этот факт можно легко упускать из виду, что, как правило, вызывает ошибки, такие как Matrix dimensions must agree . Рассмотрим следующий пример:

t = 0:0.1:10;        % Declaring a time vector
y = sin(t);          % Declaring a function

dy_dt = diff(y);     % calculates dy/dt for y = sin(t)

Предположим, мы хотим построить эти результаты. Мы рассмотрим размеры массива и посмотрим:

size(y) is 1x101
size(t) is 1x101

Но:

size(dy_dt) is 1x100

Массив на один элемент короче!

Теперь представьте, что у вас есть данные измерений позиций с течением времени и вы хотите вычислить jerk (t) , вы получите массив на 3 элемента меньше, чем временный массив (потому что рывок является дифференцированным положением 3 раза).

vel = diff(y);       % calculates velocity vel=dy/dt for y = sin(t)  size(vel)=1x100
acc = diff(vel);     % calculates acceleration acc=d(vel)/dt         size(acc)=1x99
jerk = diff(acc);    % calculates jerk jerk=d(acc)/dt                size(jerk)=1x98   

И тогда операции вроде:

x = jerk .* t;          % multiplies jerk and t element wise

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

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

Ошибки несоответствия размеров

Ошибки несоответствия размеров обычно появляются, когда:

  • Не обращая внимания на форму возвращаемых переменных из вызовов функций / методов. Во многих встроенных функциях MATLAB матрицы преобразуются в векторы для ускорения вычислений, а возвращаемая переменная может быть вектором, а не ожидаемой матрицей. Это также распространенный сценарий, когда задействована логическая маскировка .
  • Использование несовместимых размеров массива при вызове неявного расширения массива .

Использование «i» или «j» в качестве мнимой единицы, индексов цикла или общей переменной.

Рекомендация

Поскольку символы i и j могут представлять существенно разные вещи в MATLAB, их использование в качестве индексов цикла разделило сообщество пользователей MATLAB с возрастом. Хотя некоторые исторические соображения производительности могут помочь балансу опираться на одну сторону, это уже не так, и теперь выбор полностью зависит от вас и методов кодирования, которые вы выбираете.

В настоящее время официальными рекомендациями Mathworks являются:

  • Поскольку i является функцией, ее можно переопределить и использовать в качестве переменной. Однако лучше избегать использования i и j для имен переменных, если вы собираетесь использовать их в сложной арифметике.
  • Для скорости и улучшенной устойчивости в сложной арифметике используйте 1i и 1j вместо i и j .

По умолчанию

В MATLAB по умолчанию буквы i и j являются встроенными именами function , которые оба относятся к мнимой единице в сложном домене.

Таким образом, по умолчанию i = j = sqrt(-1) .

>> i
ans =
   0.0000 + 1.0000i
>> j
ans =
   0.0000 + 1.0000i

и как и следовало ожидать:

>> i^2
ans =
    -1

Используя их как переменную (для индексов цикла или другой переменной)

MATLAB позволяет использовать встроенное имя функции в качестве стандартной переменной. В этом случае используемый символ больше не будет указывать на встроенную функцию, а на вашу собственную пользовательскую переменную. Однако эта практика обычно не рекомендуется, так как это может привести к путанице, сложной отладке и обслуживанию ( см. Другой пример do-not-name-a-variable-with-an-existing-function-name ).

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

>> A = nan(2,3);
>> for i=1:2        % perfectly legal loop construction
       for j = 1:3
        A(i, j) = 10 * i + j;
       end
   end

Обратите внимание, что индексы цикла не заканчиваются в конце цикла, поэтому они сохраняют новое значение.

>> [ i ; j ]
ans =
     2
     3

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

Если позже, вам нужно отменить затенение встроенной функции (=, например, вы хотите, чтобы i и j отображали мнимую единицу снова), вы можете clear переменные:

>> clear i j

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

Если ожидаемая сложная арифметика не ожидается, использование i и j вполне функционально, и нет штрафа за производительность.


Используя их как мнимую единицу:

Если ваш код должен иметь дело со complex числами, то i и j , безусловно, пригодится. Однако для устранения неоднозначности и даже для выступлений рекомендуется использовать полную форму вместо сокращенного синтаксиса. Полная форма равна 1i (или 1j ).

>> [ i ; j ; 1i ; 1j]
ans =
   0.0000 + 1.0000i
   0.0000 + 1.0000i
   0.0000 + 1.0000i
   0.0000 + 1.0000i

Они представляют одно и то же значение sqrt(-1) , но более поздняя форма:

  • более явным, семантическим образом.
  • (кто-то, смотрящий на ваш код позже, не должен будет читать код, чтобы узнать, является ли i или j переменной или мнимой единицей).
  • быстрее (источник: Mathworks).

Обратите внимание, что полный синтаксис 1i действителен с любым числом, предшествующим символу:

>> a = 3 + 7.8j
a =
   3.0000 + 7.8000i

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


Ловушки

Хотя их использование в качестве мнимой единицы ИЛИ переменной является совершенно законным, вот лишь небольшой пример того, как путаница могла бы возникнуть, если оба метода получаются смешанными:

Давайте переопределим i и сделаем его переменной:

>> i=3
i =
     3

Теперь i - переменная (удерживающая значение 3 ), но мы только преувеличиваем сокращенную нотацию мнимой единицы, полная форма по-прежнему интерпретируется правильно:

>> 3i
ans =
   0.0000 + 3.0000i

Что теперь позволяет нам строить самые неясные формулировки. Позвольте вам оценить читаемость всех следующих конструкций:

>> [ i ; 3i ; 3*i ; i+3i ; i+3*i ]
ans =
   3.0000 + 0.0000i
   0.0000 + 3.0000i
   9.0000 + 0.0000i
   3.0000 + 3.0000i
  12.0000 + 0.0000i

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

Использование `length` для многомерных массивов

В распространенной ошибке кодеры MATLAB используют функцию length для матриц (в отличие от векторов , для которых она предназначена). Функция length , как указано в ее документации , « возвращает длину наибольшего размера массива » ввода.

Для векторов возвращаемое значение length имеет два разных значения:

  1. Общее число элементов в векторе.
  2. Наибольшая размерность вектора.

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

  1. size(A) - возвращает вектор строки, элементы которого содержат количество элементов вдоль соответствующего размера A
  2. numel(A) - возвращает количество элементов в A Эквивалентен prod(size(A)) .
  3. ndims(A) - возвращает количество измерений в массиве A Эквивалент numel(size(A)) .

Это особенно важно при написании «перспективных», векторизованных библиотечных функций, входы которых неизвестны заранее и могут иметь различные размеры и формы.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow