web-dev-qa-db-fra.com

Comment tester des entiers dans MATLAB?

J'écris un programme qui va calculer des factorielles d'entiers. Cependant, la partie sur laquelle je suis coincé est que si quelqu'un entre un non-entier tel que 1.3, j'aimerais pouvoir tester l'entrée et afficher "The number you have entered is not an integer"

18
Ryan

Vous pouvez utiliser la fonction mod , qui renvoie le reste après la division. Tous les nombres entiers sont divisibles par 1. Donc, un bon test pour non-entier serait 

integerTest=~mod(value,1);

Ceci retourne 0 si value n'est pas un entier et 1 si c'est le cas. Vous pouvez ensuite l'utiliser comme condition pour rejeter les entrées utilisateur non entières.

27
abcd

Voici une autre variante (vous pouvez voir qu'il est utilisé dans ISIND function: edit isind.m):

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

Sur ma machine, c'est plus rapide que les autres solutions proposées:

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

Horaires:

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

Vous pouvez convertir la valeur en entier et revenir en double et comparer le résultat à la valeur d'origine:

 >> x = 1,3; 
 >> x == double (uint64 (x)) 

 ans = 

 0 

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

 Ans = 

 1

Il est intéressant de noter que l'approche de R.M. d'utilisation de MOD s'exécute plus rapidement dans une boucle et l'approche de conversion ci-dessus s'exécute plus rapidement lorsqu'elle est vectorisée:

 >> x = Rand (100000, 1); 
 >> tic; pour ii = 1: 100000; ~ mod (x (ii), 1); fin; toc; 
 Le temps écoulé est de 0.018380 secondes .
 >> tic. pour ii = 1: 100000; x(ii) == double (uint64 (x (ii))); fin; toc; 
 Le temps écoulé est de 0,383020 secondes .
 >> tic; ~ mod (x, 1); toc; 
 Le temps écoulé est égal à 0.005299 secondes .
 >> tic; x == double (uint64 (x)); toc; 
 Le temps écoulé est de 0.002971 secondes .
4
b3.

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

Vous pouvez facilement ajouter d’autres vérifications (comme pour la positivité).

Edité avec isinteger. Merci @SolarStatistics, je n'avais pas remarqué qu'ils avaient ajouté cette fonctionnalité. Edité à nouveau à la réponse originale à nouveau comme isinteger n'est pas approprié (voir commentaires ci-dessous).

2
MatlabSorter

Comme indiqué par @nibot isinteger teste l’entrée sous la forme d’un entier TYPE. Au lieu de cela, vous pouvez vérifier si l’arrondi entrée renvoie la même valeur que input . par exemple:

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

par exemple

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

Je voulais simplement souligner que les méthodes fournies vérifient toutes si l'entrée est un entier gaussien, ce qui signifie que les parties réelle et imaginaire sont les deux entier. Si vous devez vous soucier de la partie imaginaire, vous devez la traiter séparément.

Pour mes applications, les entrées avec des composants imaginaires ne doivent pas être considérées comme un entier valide. J'ai donc ceci:

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

En utilisant les tests de b3.'s:

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

L'appel en boucle est un peu plus lent, principalement à cause de la surcharge de la fonction. En remplaçant l'expression arithmétique par ~ mod (dataInput, 1), elle ne sera que 50% plus rapide que le code qui recherche les parties imaginaires.

0
Setsu