Я пишу программу, которая будет вычислять факториалы целых чисел. Тем не менее, часть, на которую я застрял, - это если кто-то вводит нецелое число, например 1.3
, я бы хотел проверить вход и отображение "The number you have entered is not an integer"
Как проверить для целых чисел в MATLAB?
Ответ 1
Вы можете использовать функцию mod
, которая возвращает остаток после деления. Все целые числа делятся на 1
. Таким образом, хороший тест для нецелого числа будет
integerTest=~mod(value,1);
Это возвращает 0
, если value
не является целым числом и 1
, если оно есть. Затем вы можете использовать это как условие для отклонения нецелевых пользовательских входов.
Ответ 2
Вот еще один вариант (вы можете видеть, что он используется в 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.
Ответ 3
Вы можете присвоить значение целому числу и вернуться к двойному и проверить результат на исходное значение:
>> 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.
Ответ 4
assert(isnumeric(input) && round(input) == input, 'That number is not an integer.')
Вы также можете легко добавить другие проверки (например, для позитивности).
Отредактировано с помощью isinteger
. Спасибо @SolarStatistics
, я не заметил, что они добавили эту функциональность.
Отредактировано обратно к исходному ответу снова, поскольку isinteger
не подходит (см. Комментарии ниже).
Ответ 5
Как указано в тестах @nibot isinteger для ввода как целочисленного ТИПА. Вместо этого вы можете проверить, возвращает ли округление входное значение того же значения, что и вход. например:
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.')
>>
Ответ 6
Я просто хотел указать, что предоставленные методы проверяют, является ли вход гауссовским целым, что означает, что действительная и мнимая части оба целые числа. Если вам нужно заботиться о воображаемой части, вам нужно разобраться с ней отдельно.
Для моих приложений входные данные с мнимыми компонентами не должны считаться действительным целым числом, поэтому у меня есть следующее:
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% быстрее, чем код, который проверяет мнимые части.
Ответ 7
В команде 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