J'ai été surpris d'apprendre que R ne vient pas avec une fonction pratique pour vérifier si le nombre est entier.
is.integer(66) # FALSE
Les fichiers d'aide avertissent :
is.integer(x)
ne teste pas six
contient des nombres entiers! Pour cela, utilisezround
, comme dans la fonctionis.wholenumber(x)
dans les exemples.
L'exemple a cette fonction personnalisée comme "solution de contournement"
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 irait dans le sens de
check.integer <- function(x) {
x == round(x)
}
Où mon approche échouerait-elle? Quel serait votre travail si vous étiez à ma place hypothétique?
round(x)
est mis en œuvre correctement, le résultat de son application à un entier serait toujours cet entier ...is.integer
vérifie le concept de calcul, lacheck.integer
fonction utilisateur vérifie le point de vue mathématique.Réponses:
Une autre alternative consiste à vérifier la partie fractionnaire:
ou, si vous souhaitez vérifier dans une certaine tolérance:
la source
x <- 5-1e-8; x%%1
donne 0,9999999 (ce qui impliquerait sitol==1e-5
par exemple) quix
n'est pas un entier.min(abs(c(x%%1, x%%1-1))) < tol
plutôt queabs(min(x%%1, x%%1-1)) < tol
sinon, vous obtiendrezFALSE
pour n'importe quel entier ...as.integer(x) == x
? Il ne rejettera pas 3 ou 3.0 comme leis.integer(x)
ferait, et il attrapera 3.1.Voici une solution utilisant des fonctions plus simples et pas de hacks:
De plus, vous pouvez tester un vecteur entier à la fois, si vous le souhaitez. Voici une fonction:
Vous pouvez le modifier pour l'utiliser
*apply
dans le cas de vecteurs, matrices, etc.la source
if
else
pourrait être fait simplementisTRUE(test)
. En effet, c'est tout ce dont vous avez besoin pour remplacer laif
else
clause et lesreturn
instructions car R renvoie automatiquement le résultat de la dernière évaluation.testInteger(1.0000001)
[1] FALSEtestInteger(1.00000001)
[1] TRUEall(a == as.integer(a))
contourne ce problème!La lecture de la documentation du langage R
as.integer
a plus à voir avec la façon dont le nombre est stocké que s'il est pratiquement équivalent à un entier.is.integer
teste si le nombre est déclaré comme un entier. Vous pouvez déclarer un entier en mettant unL
après.Des fonctions comme
round
renverront également un entier déclaré, ce que vous faites avecx==round(x)
. Le problème avec cette approche est ce que vous considérez être pratiquement un entier. L'exemple utilise moins de précision pour tester l'équivalence.Donc, en fonction de votre application, vous pourriez avoir des problèmes de cette façon.
la source
Voici un moyen apparemment fiable:
Cette solution permet également d'utiliser des nombres entiers en notation scientifique:
la source
check.integer(1e4)
c'est VRAI, alors quecheck.integer(1e5)
c'est FAUX.is.wholenumber
, ou l'une des autres solutions fournies dans d'autres réponses. Ceux - ci ne devraient pas être différentes:check.integer(1e22); check.integer(1e23)
. Vous pouvez évidemment changer l'expression régulière pour résoudre ce problème, mais cette approche est affreuse. (Le commentaire provient de l'attribution dans le package installr.)format(40, scientific = FALSE, digits = 20)
place. J'ai mis à jour la réponse. Merci de l'avoir repéré.1.0000000000000001 == 1L [1] TRUE
. Mais ma solution est meilleure si vous obtenez déjà un nombre sous forme de chaînecheck.integer("1000000000000000000000000000000000001") [1] TRUE
Il semble que vous ne voyiez pas la nécessité d'incorporer une certaine tolérance d'erreur. Cela ne serait pas nécessaire si tous les entiers étaient entrés sous forme d'entiers, mais parfois ils résultent d'opérations arithmétiques qui perdent une certaine précision. Par exemple:
Notez que ce n'est pas la faiblesse de R, tous les logiciels informatiques ont des limites de précision.
la source
De
Hmisc::spss.get
:option beaucoup plus sûre, à mon humble avis, car elle «contourne» le problème de précision de la machine. Si vous essayez
is.integer(floor(1))
, vous obtiendrezFALSE
. BTW, votre entier ne sera pas enregistré en tant qu'entier s'il est supérieur à la.Machine$integer.max
valeur, qui est, par défaut, 2147483647, alors changez lainteger.max
valeur ou effectuez les vérifications alternatives ...la source
x <- sqrt(2)^2
, puisall(floor(x) == x, na.rm = TRUE)
retourFALSE
vous pouvez utiliser une condition if simple comme:
la source
Dans R, si un nombre est numérique ou entier peut être déterminé par la fonction de classe. Généralement, tous les nombres sont stockés sous forme numérique et pour définir explicitement un nombre comme entier, nous devons spécifier «L» après le nombre.
Exemple:
[1] "numérique"
[1] "entier"
J'espère que c'est ce dont nous avions besoin. Merci :)
la source
[MISE À JOUR] =============================================== ===============
En ce qui concerne la réponse [ANCIENNE] ci-dessous, j'ai découvert que cela fonctionnait parce que j'ai mis tous les nombres dans un seul vecteur atomique; l'un d'eux était un personnage, donc chacun devient des personnages.
Si nous utilisons une liste (par conséquent, la coercition ne se produit pas) tout le test passe correctement sauf un:,
1/(1 - 0.98)
qui reste unnumeric
. En effet, letol
paramètre est par défaut100 * .Machine$double.eps
et ce nombre est loin d'être un50
peu inférieur au double de cela. Donc, en gros, pour ce genre de chiffres, nous avons à décider de notre tolérance!Donc si vous voulez que tous les tests deviennent
TRUE
, vous pouvezassertive::is_whole_number(x, tol = 200 * .Machine$double.eps)
Quoi qu'il en soit, je confirme que l'affirmation de l'OMI reste la meilleure solution.
Ci-dessous un reprex pour cette [MISE À JOUR].
Créé le 23/07/2019 par le package reprex (v0.3.0)
[ANCIEN] =============================================== ===================
IMO la meilleure solution vient du
assertive
package (qui, pour le moment, résout tous les exemples positifs et négatifs de ce fil):Créé le 23/07/2019 par le package reprex (v0.3.0)
la source
Si vous préférez ne pas écrire votre propre fonction, essayez à
check.integer
partir du package installr . Actuellement, il utilise la réponse de VitoshKa.Essayez également le
check.numeric(v, only.integer=TRUE)
package varhandle , qui a l'avantage d'être vectorisé.la source
Une fois peut également utiliser
dplyr::near
:Il s'applique à n'importe quel vecteur
a
et possède un paramètre de tolérance facultatif.la source
Je ne suis pas sûr de ce que vous essayez d'accomplir. Mais voici quelques réflexions:
1. Convertir en entier:
num = as.integer(123.2342)
2. Vérifier si une variable est un entier:
is.integer(num)
typeof(num)=="integer"
la source