144 votes

comment vérifier si le nombre est entier ?

J'ai été surpris d'apprendre que R n'est pas livré avec une fonction pratique pour vérifier si le nombre est entier.

is.integer(66) # FALSE

Les fichiers d'aide préviennent :

is.integer(x) ne teste pas si x contient des nombres entiers ! Pour cela, utilisez round comme dans la fonction is.wholenumber(x) dans les exemples.

L'exemple comporte cette fonction personnalisée comme "solution de rechange".

is.wholenumber <- function(x, tol = .Machine$double.eps^0.5)  abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE

Si je devais écrire une fonction pour vérifier les entiers, en supposant que je n'ai pas lu les commentaires ci-dessus, j'écrirais une fonction qui ressemblerait à quelque chose comme

check.integer <- function(x) {
    x == round(x)
}

Où mon approche échouerait-elle ? Que feriez-vous si vous étiez à ma place ?

0 votes

J'espère que si round(x) est implémentée correctement, le résultat de son application à un entier serait toujours cet entier...

1 votes

Jetez un coup d'œil à la FAQ sur R cran.r-project.org/doc/FAQ/

5 votes

> check.integer(9.0) [1] VRAI ce n'est pas le cas.

170voto

James Points 24725

Une autre alternative consiste à vérifier la partie fractionnaire :

x%%1==0,

ou,

abs(min(x%%1, x%%1-1)) < tol,

si vous voulez vérifier dans une certaine tolérance.

1 votes

la suggestion de vérification des tolérances fonctionne-t-elle vraiment ?? x <- 5-1e-8; x%%1 donne 0.9999999 (ce qui impliquerait si tol==1e-5 par exemple) que x est pas un nombre entier.

0 votes

@BenBolker Bonne prise, cela fonctionne pour les perturbations positives je pense. Je l'ai changé en une solution alternative qui devrait fonctionner.

2 votes

@James, je pense que ça devrait être min(abs(c(x%%1, x%%1-1))) < tol au lieu de abs(min(x%%1, x%%1-1)) < tol sinon, vous obtiendrez FALSE pour tout nombre entier...

39voto

Iterator Points 10485

Voici une solution utilisant des fonctions plus simples et sans bidouillage :

all.equal(a, as.integer(a))

De plus, vous pouvez tester tout un vecteur à la fois, si vous le souhaitez. Voici une fonction :

testInteger <- function(x){
  test <- all.equal(x, as.integer(x), check.attributes = FALSE)
  if(test == TRUE){ return(TRUE) }
  else { return(FALSE) }
}

Vous pouvez le changer pour utiliser *apply dans le cas des vecteurs, des matrices, etc.

12 votes

La dernière if else pourrait être fait avec simplement isTRUE(test) . En effet, c'est tout ce dont vous avez besoin pour remplacer le if else et de la clause return car R renvoie automatiquement le résultat de la dernière évaluation.

8 votes

testInteger(1.0000001) [1] FAUX testInteger(1.00000001) 1] VRAI

3 votes

all(a == as.integer(a)) permet de contourner ce problème".

11voto

VitoshKa Points 4689

Voici un moyen, apparemment fiable :

check.integer <- function(N){
    !length(grep("[^[:digit:]]", as.character(N)))
}

check.integer(3243)
#TRUE
check.integer(3243.34)
#FALSE
check.integer("sdfds")
#FALSE

Edit : pour permettre aux entiers spécifiés en notation scientifique de faire comme ceci :

check.integer <- function(N){
    !length(grep("[^[:digit:]]", format(N, scientific = FALSE)))
}

1 votes

Ça ne me semble pas très fiable : check.integer(1e4) est VRAI, tandis que check.integer(1e5) est FAUX.

6 votes

-1 C'est pire que is.wholenumber ou toute autre solution proposée dans d'autres réponses. Celles-ci ne devraient pas être différentes : check.integer(1e22); check.integer(1e23) . Vous pouvez évidemment modifier le regex pour corriger cela, mais cette approche est épouvantable. (Le commentaire provient de l'attribution dans le paquet installr).

0 votes

@Joshua, Votre commentaire est complètement trompeur pour trois raisons. Tout d'abord, 1e22 dans votre exemple ne peut pas être représenté de manière précise, et toutes les solutions non basées sur les regexp échoueront. Par exemple, la solution maintenant acceptée (1e20+1.1)%%1 vous donnera 0 avec un avertissement ! Deuxièmement, cette chaîne représente-t-elle un entier "13132131213232321123213" ? Si vous pensez que oui, alors ma solution est la seule qui fonctionne !

11voto

Andrew Redd Points 1693

Lire la documentation du langage R, as.integer a plus à voir avec la façon dont le nombre est stocké qu'avec le fait qu'il soit pratiquement équivalent à un nombre entier. as.integer teste si le nombre est déclaré comme un nombre entier. Vous pouvez déclarer un nombre entier en mettant un L après elle.

> is.integer(66L)
[1] TRUE

Des fonctions comme round retournera un entier déclaré, ce qui est ce que vous faites avec x==round(x) . Le problème avec cette approche est de savoir ce que vous considérez comme étant pratiquement un nombre entier. L'exemple utilise une précision moindre pour tester l'équivalence.

> is.wholenumber(1+2^-50)
[1] TRUE
> check.integer(1+2^-50)
[1] FALSE

En fonction de votre demande, vous pourriez donc avoir des problèmes de cette manière.

1 votes

La deuxième ligne dit "as.integer teste si le nombre est déclaré comme un entier", mais je suis presque sûr que vous vouliez dire "is.integer". Il ne s'agit que d'une modification d'un caractère, je ne pouvais donc pas la changer facilement.

9voto

Aniko Points 7555

Il semble que vous ne voyez pas la nécessité d'intégrer une certaine tolérance d'erreur. Cela ne serait pas nécessaire si tous les nombres entiers étaient saisis en tant que tels, mais parfois ils résultent d'opérations arithmétiques qui perdent un peu de précision. Par exemple :

> 2/49*49
[1] 2
> check.integer(2/49*49)
[1] FALSE 
> is.wholenumber(2/49*49)
[1] TRUE

Notez que ce n'est pas la faiblesse de R, tous les logiciels informatiques ont des limites de précision.

3 votes

juste au cas où certains ne comprendraient pas bien ce qui s'est passé ici... si vous entrez as.integer(2/49*49) vous obtenez 1 ! !! (BTW, il est toujours aussi frustrant que R ne présente pas le résultat du calcul initial comme 2.0 pour représenter que la valeur a une composante décimale) voir... stackoverflow.com/questions/1535021/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X