Матлаб пьет вашу кровь

Sep 16, 2014 22:40

У нас есть достаточно большой проект на Matlab. Своего матлаб-кода порядка 15 KLOC. Писать на Matlab столько кода - занятие не для слабонервных. Ниже приведен список некоторых особенностей матлаба.


  1. Размер java heap memory нельзя выставить больше четверти физического размера ОЗУ. Что для некоторых используемых нами java либ уже не хватает.

  2. В Матлаб есть функция spconvert - импорт разреженных матриц в координатном формате из файла. А вот аналогичной функция для экспорта - нет

  3. Экспорт матриц для double чисел корректно работает только в ascii формате, см. http://www.mathworks.com/matlabcentral/answers/100620-how-can-i-avoid-truncation-and-loss-of-precision-when-saving-my-data-in-matlab. В другом формате при экспорте числа будут "обрезаться" до single

  4. Эффективность объектно-ориентированного кода крайне невелика. Скорость доступа к полям объекта, к enum'ам настолько мала, что использовать ООП для сколько-нибудь реальных задач невозможно

  5. Функция linsolve не работает для разреженных матриц. Например:
    >> linsolve(sprand(3,3,0.1), sprand(3,1,1))
    Error using linsolve
    Linsolve is currently not supported for sparse inputs

    Вместо этого предлагается использовать "\"

  6. Стандартные функции можно случайно переопределить. Например:
    >> diag(randi(3,3))
    ans =
    3
    2
    3
    >> diag = 1;
    >> diag(randi(3,3))
    ??? Index exceeds matrix dimensions.

  7. Сокращенная запись массивов без запятых может привести к таким опечаткам:
    >> [1 -1, 2]
    ans =
    1 -1 2

    >> [1 - 1, 2] % случайно поставили пробел перед второй единицей
    ans =
    0 2


  8. В workspace формат вывода по умолчанию "укороченный" и поменять его нельзя

  9. Не вполне очевидная работа с размерностью данных
    >> size(1)
    ans =
    1 1

    >> size([1 2])
    ans =
    1 2

    >> size([])
    ans =
    0 0

    Такая операция выполнима
    >> [] * 1
    ans =
    []

    А такая уже нет:

    >> [] * [1 2]
    ??? Error using ==> mtimes
    Inner matrix dimensions must agree

  10. Малоинформативные сообщения об ошибках. Например, описываем в файле класс :
    classdef struc
    properties
    x
    end
    end

    Работаем в командной строке:

    >> a = struc();
    >> a(1) = struc()
    >> a([]).x * 1
    ??? Error using ==> mtimes
    Not enough input arguments.

    И

    >> class(a([]).x)
    ??? Error using ==> class
    Not enough input arguments.

    Обратите внимание на описание ошибки "для операции умножения не хватает аргументов". Хотя здесь должно было быть сообщение об отсутствующем объекте по заданному индексу.

    Продолжим пример и создадим массив объектов, для чего используется специальный синтаксис. Так, например, делать нельзя:
    >> a = [];
    >> a(1) = struc()
    ??? The following error occurred converting from struc to double:
    Error using ==> double
    Conversion to double from struc is not possible.

    А вот так уже можно:

    >> a=struc();
    >> a(2) = struc();
    >> a(11) = struc();
    >> a
    a =
    1x11 struc

    Автоматически вызываются конструкторы для объектов по индексам от 3 до 10. Соответственно, в массиве объектов контроля выхода за пределы массива уже не происходит.

  11. Матлаб жесток к тем, кто допускает опечатки в коде:
    function [x,z] = f(x,z)
    y.field = 1; % случайно вместо переменной "z" изменили поле в "y".
    end

    И, несмотря на то, что переменная "y" нигде не объявлена, несмотря на то, что мы явно используем поле "field" необъявленной переменной - матлаб при статической проверке кода предупреждения на этой строке не выдаст. Вызов такой функции отработает "молча".

    Другой пример, который при проверке не вызовет предупреждений:

    function [ a ] = fun1( a,i,b )
    a(i) = b;
    a(i2) = b+1; % вместо "i" случайно написали 'i2"
    a(i) = a1(i);
    end

    Вызывая такую функцию, получим ожидаемую ошибку:

    >> fun1(1:10,2,3)
    Undefined function or variable 'i2'.

    Error in fun1 (line 3)

  12. В матлабе фактическим именем функции является не ее имя в сигнатуре, а имя файла, в коротом она описана. Например, файл: function1.m

    function [ output_args ] = fun1( input_args )
    42
    end

    Пишем в командной строке:

    >> fun1()
    ??? Undefined function or variable 'fun1'.

    А так можно:

    >> function1()
    ans =
    42

  13. Работа с хэш-массивами не вполне очевидна:

    kv = containers.Map('KeyType','int32', 'ValueType', 'any');
    % ...заполянем "kv" значениями...
    for k = keys(kv) % последовательно выводим на экран ключи нашего хэша
    kv(k{1})
    end

    Если вместо k{1} написать k, то будет ошибка, т.к. ключи перечисляются внутри cell-массива

prog, matlab

Previous post Next post
Up