Как мне проверить целые числа в MATLAB? - PullRequest
18 голосов
/ 22 марта 2011

Я пишу программу, которая будет вычислять факториалы целых чисел.Тем не менее, часть, на которой я застрял, - это если кто-то вводит нецелое число, такое как 1.3, я хотел бы иметь возможность проверить ввод и отобразить "The number you have entered is not an integer"

Ответы [ 7 ]

27 голосов
/ 22 марта 2011

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

integerTest=~mod(value,1);

Возвращает 0, если value не является целым числом, и 1, если оно есть. Затем вы можете использовать это как условие для отклонения нецелых пользовательских вводов.

22 голосов
/ 02 августа 2011

Вот еще один вариант (вы можете видеть, что он используется в ISIND функции: edit isind.m):

integerTest = ( x == floor(x) );

На моей машине это быстрее, чем другие предлагаемые решения:

%# create a vector of doubles, containing integers and non-integers
x = (1:100000)';                       %'
idx = ( rand(size(x)) < 0.5 );
x(idx) = x(idx) + rand(sum(idx),1);

%# test for integers
tic, q1 = ~mod(x, 1); toc
tic, q2 = x==double(uint64(x)); toc
tic, q3 = x==floor(x); toc

%# compare results
assert( isequal(q1,q2,q3) )

Тайминги:

Elapsed time is 0.012253 seconds.
Elapsed time is 0.014201 seconds.
Elapsed time is 0.005665 seconds.
4 голосов
/ 22 марта 2011

Вы можете привести значение к целому числу и обратно к двойному, и сравнить результат с исходным значением:

>> x = 1.3;
>> x == double(uint64(x))

ans =

     0

>> x = 2;
>> x == double(uint64(x))

ans =

     1

Интересно, что подход R.M. использования MOD работает быстрее в цикле, и вышеупомянутый подход приведения выполняется быстрее при векторизации:

>> x = rand(100000, 1);
>> tic; for ii = 1:100000; ~mod(x(ii), 1); end; toc;
Elapsed time is 0.018380 seconds.
>> tic; for ii = 1:100000; x(ii) == double(uint64(x(ii))); end; toc;
Elapsed time is 0.383020 seconds.
>> tic; ~mod(x, 1); toc;
Elapsed time is 0.005299 seconds.
>> tic; x == double(uint64(x)); toc;
Elapsed time is 0.002971 seconds.
2 голосов
/ 22 марта 2011

assert(isnumeric(input) && round(input) == input, 'That number is not an integer.')

Вы также можете легко добавить другие проверки (например, для позитивности).

Редактируется с помощью isinteger.Спасибо @SolarStatistics, я не заметил, что они добавили эту функцию.Отредактировано обратно к исходному ответу снова как isinteger не подходит (см. Комментарии ниже).

0 голосов
/ 05 февраля 2015

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

Для моих приложений входные данные с мнимыми компонентами не должны рассматриваться как допустимое целое число, поэтому у меня есть следующее:

function boolResult = fnIsInteger(input)
    %validate input
    if isempty(input)
        error('Input cannot be empty')
    elseif ~isnumeric(input)
        error('Input must be numeric')
    end

    boolResult = (imag(input) == 0) & (round(input) == input);
end

Использование тестов b3.:

>> x = rand(100000, 1);
>> tic; for ii = 1:100000; ~mod(x(ii), 1); end; toc;
Elapsed time is 0.003960 seconds.
>> tic; for ii = 1:100000; fnIsInteger(x(ii)); end; toc;
Elapsed time is 0.217397 seconds.
>> tic; ~mod(x, 1); toc;
Elapsed time is 0.000967 seconds.
>> tic; fnIsInteger(x); toc;
Elapsed time is 0.003195 seconds.

Зацикленный вызов немного медленнее, в основном из-за перегрузки функции.Замена арифметического выражения на ~ mod (dataInput, 1) сделает его только на 50% быстрее, чем код, проверяющий мнимые части.

0 голосов
/ 13 мая 2013

По команде double вы не можете получить правильный ответ:

>> double(uint64(21/22))
ans =
     1
>> double(uint64(22/22))
ans =
     1

также floor, round, ... возникают проблемы в таких случаях:

floor(22/22)==21.99999999999999999999999999999999999/22

но mod, кажется, может различать 22/22 и 21.99999999999999999999999999999999999/22:

>> mod(22,22)
ans =
     0
>> (21.99999999999999999999999999999999999/22)
ans =
     1
0 голосов
/ 22 марта 2011

Как указывает @nibot isinteger проверяет входные данные как целочисленный ТИП. Вместо этого вы можете проверить, возвращает ли округление input то же значение, что и input . например:

assert(abs(round(input)-input))<eps*2,'That number is not an integer.')

например

>> input=1.3;
>> assert(abs(round(input)-input)<eps*2,'That number is not an integer.')
??? That number is not an integer.

>> input=3;
>> assert(abs(round(input)-input)<eps*2,'That number is not an integer.')
>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...