Ryan
Ryan

Reputation: 181

How do I test for integers in MATLAB?

I'm writing a program that will calculate factorials of integers. However, the part I'm stuck on is if someone enters a non-integer such as 1.3, I'd like to be able to test the input and display "The number you have entered is not an integer"

Upvotes: 18

Views: 69920

Answers (7)

Setsu
Setsu

Reputation: 1228

I just wanted to point out that the provided methods all test for whether the input is a Gaussian integer, meaning that the real and imaginary parts are both integers. If you need to care about the imaginary part then you need to deal with it separately.

For my applications, inputs with imaginary components shouldn't be considered a valid integer, so I have this:

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

Using b3.'s tests:

>> 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.

The looped call is quite a bit slower mostly due to the function overhead. Replacing the arithmetic expression with ~mod(dataInput, 1) will make it only 50% faster than the code that checks for imaginary parts.

Upvotes: 0

Hossein Tavakoli
Hossein Tavakoli

Reputation: 1

By double command, you cannot get the correct answer:

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

also floor,round,... have problem with such cases:

floor(22/22)==21.99999999999999999999999999999999999/22

but mod seems can distinguish 22/22 and 21.99999999999999999999999999999999999/22:

>> mod(22,22)
ans =
     0
>> (21.99999999999999999999999999999999999/22)
ans =
     1

Upvotes: -1

MatlabSorter
MatlabSorter

Reputation: 1300

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

You could add other checks, (like for positivity) easily as well.

Edited using isinteger. Thanks @SolarStatistics, I hadn't noticed they added this functionality. Edited back to original answer again as isinteger isn't appropriate (see comments below).

Upvotes: 2

Amro
Amro

Reputation: 124563

Here is another variation (you can see it being used in ISIND function: edit isind.m):

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

On my machine, it is faster than the other proposed solutions:

%# 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) )

Timings:

Elapsed time is 0.012253 seconds.
Elapsed time is 0.014201 seconds.
Elapsed time is 0.005665 seconds.

Upvotes: 22

b3.
b3.

Reputation: 7165

You can cast the value to an integer and back to a double and check the result against the original value:

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

ans =

     0

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

ans =

     1

Interestingly, R.M.'s approach of using MOD runs faster in a loop and the above casting approach runs faster when vectorized:

>> 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.

Upvotes: 4

Azim J
Azim J

Reputation: 8290

As point out by @nibot isinteger tests for the input as an integer TYPE. Instead you could check to see if rounding input returns the same value as input. eg:

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

for example

>> 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.')
>> 

Upvotes: 0

abcd
abcd

Reputation: 42225

You can use the mod function, which returns the remainder after division. All integers are divisible by 1. So a good test for non-integer would be

integerTest=~mod(value,1);

This returns 0 if value is not an integer and 1 if it is. You can then use this as a conditional to reject non-integer user inputs.

Upvotes: 28

Related Questions