web-dev-qa-db-fra.com

Vérifier si le nombre est entier

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

Le fichiers d'aide avertit :

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 a cette fonction personnalisée comme une "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?

87
Roman Luštrik

Une autre alternative est de vérifier la partie décimale:

x%%1==0

ou, si vous voulez vérifier avec une certaine tolérance:

min(abs(c(x%%1, x%%1-1))) < tol
107
James

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

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 de vecteurs, matrices, etc.

28
Iterator

Voici un moyen apparemment fiable:

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

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

Cette solution permet également des entiers en notation scientifique:

> check.integer(222e3)
[1] TRUE
9
VitoshKa

En lisant la documentation en langage R, as.integer A plus à voir avec la façon dont le numéro est stocké que s'il est pratiquement équivalent à un entier. is.integer Vérifie si le nombre est déclaré sous forme d'entier. Vous pouvez déclarer un entier en mettant un L après celui-ci.

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

Des fonctions comme round renverront également un entier déclaré, ce que vous faites avec x==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.

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

Donc, en fonction de votre application, vous pourriez avoir des problèmes de cette façon.

9
Andrew Redd

Il semble que vous ne voyiez pas la nécessité d’incorporer une certaine tolérance aux erreurs. Il ne serait pas nécessaire que tous les nombres entiers soient entrés sous forme d'entiers, mais ils résultent parfois d'opérations arithmétiques qui perdent une certaine 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 ont des limites de précision.

8
Aniko

De Hmisc::spss.get:

all(floor(x) == x, na.rm = TRUE)

option beaucoup plus sûre, à mon humble avis, car il "contourne" le problème de précision de la machine. Si vous essayez is.integer(floor(1)), vous obtiendrez FALSE. En passant, votre entier ne sera pas sauvegardé sous la forme d'un entier s'il est supérieur à la valeur .Machine$integer.max, Qui correspond par défaut à 2147483647; changez donc la valeur integer.max Ou effectuez les vérifications alternatives ...

6
aL3xa

vous pouvez utiliser simple si condition comme:

if(round(var) != var)­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
3
Meru Patil

Dans R, le fait qu'un nombre soit numérique ou entier peut être déterminé par la fonction de classe. En général, tous les nombres sont stockés sous forme numérique et pour définir explicitement un nombre sous forme d’entier, nous devons spécifier "L" après le nombre.

Exemple:

x <- 1

classe (x)

[1] "numérique"

x <- 1L

classe (x)

[1] "entier"

J'espère que c'est ce qui était nécessaire. Merci :)

1
Meenansha Sachdeva

[UPDATE] ============================================= ===============

En ce qui concerne la réponse [OLD] 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, alors chacun devient des personnages.

Si nous utilisons une liste (par conséquent, la coercition ne se produit pas), tout le test réussit correctement, sauf un: 1/(1 - 0.98), qui reste un numeric. Ceci parce que le paramètre tol est par défaut 100 * .Machine$double.eps Et que ce nombre est loin de 50 Un peu moins que le double de cela. Donc, fondamentalement, pour ce genre de nombres, nous devons décider de notre tolérance!

Donc si vous voulez que tous les tests deviennent TRUE, vous pouvez assertive::is_whole_number(x, tol = 200 * .Machine$double.eps)

Quoi qu'il en soit, je confirme que l’assurance IMO reste la meilleure solution.

Ci-dessous un reprex pour cette [UPDATE].

expect_trues_c <- c(
  cl = sqrt(2)^2,
  pp = 9.0,
  t = 1 / (1 - 0.98),
  ar0 = 66L,
  ar1 = 66,
  ar2 = 1 + 2^-50,
  v = 222e3,
  w1 = 1e4,
  w2 = 1e5,
  v2 = "1000000000000000000000000000000000001",
  an = 2 / 49 * 49,
  ju1 = 1e22,
  ju2 = 1e24,
  al = floor(1),
  v5 = 1.0000000000000001 # this is under machine precision!
)

str(expect_trues_c)
#>  Named chr [1:15] "2" "9" "50" "66" "66" "1" "222000" "10000" "1e+05" ...
#>  - attr(*, "names")= chr [1:15] "cl" "pp" "t" "ar0" ...
assertive::is_whole_number(expect_trues_c)
#> Warning: Coercing expect_trues_c to class 'numeric'.
#>                      2                      9                     50 
#>                   TRUE                   TRUE                   TRUE 
#>                     66                     66                      1 
#>                   TRUE                   TRUE                   TRUE 
#>                 222000                  10000                 100000 
#>                   TRUE                   TRUE                   TRUE 
#>                  1e+36                      2                  1e+22 
#>                   TRUE                   TRUE                   TRUE 
#> 9.9999999999999998e+23                      1                      1 
#>                   TRUE                   TRUE                   TRUE



expect_trues_l <- list(
  cl = sqrt(2)^2,
  pp = 9.0,
  t = 1 / (1 - 0.98),
  ar0 = 66L,
  ar1 = 66,
  ar2 = 1 + 2^-50,
  v = 222e3,
  w1 = 1e4,
  w2 = 1e5,
  v2 = "1000000000000000000000000000000000001",
  an = 2 / 49 * 49,
  ju1 = 1e22,
  ju2 = 1e24,
  al = floor(1),
  v5 = 1.0000000000000001 # this is under machine precision!
)

str(expect_trues_l)
#> List of 15
#>  $ cl : num 2
#>  $ pp : num 9
#>  $ t  : num 50
#>  $ ar0: int 66
#>  $ ar1: num 66
#>  $ ar2: num 1
#>  $ v  : num 222000
#>  $ w1 : num 10000
#>  $ w2 : num 1e+05
#>  $ v2 : chr "1000000000000000000000000000000000001"
#>  $ an : num 2
#>  $ ju1: num 1e+22
#>  $ ju2: num 1e+24
#>  $ al : num 1
#>  $ v5 : num 1
assertive::is_whole_number(expect_trues_l)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#> There was 1 failure:
#>   Position              Value      Cause
#> 1        3 49.999999999999957 fractional
assertive::is_whole_number(expect_trues_l, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#>     2.0000000000000004                      9     49.999999999999957 
#>                   TRUE                   TRUE                   TRUE 
#>                     66                     66     1.0000000000000009 
#>                   TRUE                   TRUE                   TRUE 
#>                 222000                  10000                 100000 
#>                   TRUE                   TRUE                   TRUE 
#>                  1e+36     1.9999999999999998                  1e+22 
#>                   TRUE                   TRUE                   TRUE 
#> 9.9999999999999998e+23                      1                      1 
#>                   TRUE                   TRUE                   TRUE



expect_falses <- list(
  bb = 5 - 1e-8,
  pt1 = 1.0000001,
  pt2 = 1.00000001,
  v3 = 3243.34,
  v4 = "sdfds"
)

str(expect_falses)
#> List of 5
#>  $ bb : num 5
#>  $ pt1: num 1
#>  $ pt2: num 1
#>  $ v3 : num 3243
#>  $ v4 : chr "sdfds"
assertive::is_whole_number(expect_falses)
#> Warning: Coercing expect_falses to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> There were 5 failures:
#>   Position              Value      Cause
#> 1        1 4.9999999900000001 fractional
#> 2        2 1.0000001000000001 fractional
#> 3        3 1.0000000099999999 fractional
#> 4        4 3243.3400000000001 fractional
#> 5        5               <NA>    missing
assertive::is_whole_number(expect_falses, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_falses to class 'numeric'.

#> Warning: NAs introduced by coercion
#> There were 5 failures:
#>   Position              Value      Cause
#> 1        1 4.9999999900000001 fractional
#> 2        2 1.0000001000000001 fractional
#> 3        3 1.0000000099999999 fractional
#> 4        4 3243.3400000000001 fractional
#> 5        5               <NA>    missing

Créé le 2019-07-23 par le package reprex (v0.3.0)

[OLD] ============================================ ===================

La meilleure solution à l’OMI provient du package assertive (qui, pour le moment, résout tous les exemples positifs et négatifs de ce fil):

are_all_whole_numbers <- function(x) {
  all(assertive::is_whole_number(x), na.rm = TRUE)
}

are_all_whole_numbers(c(
  cl = sqrt(2)^2,
  pp = 9.0,
  t = 1 / (1 - 0.98),
  ar0 = 66L,
  ar1 = 66,
  ar2 = 1 + 2^-50,
  v = 222e3,
  w1 = 1e4,
  w2 = 1e5,
  v2 = "1000000000000000000000000000000000001",
  an = 2 / 49 * 49,
  ju1 = 1e22,
  ju2 = 1e24,
  al = floor(1),
  v5 = 1.0000000000000001 # difference is under machine precision!
))
#> Warning: Coercing x to class 'numeric'.
#> [1] TRUE

are_all_not_whole_numbers <- function(x) {
  all(!assertive::is_whole_number(x), na.rm = TRUE)
}

are_all_not_whole_numbers(c(
  bb = 5 - 1e-8,
  pt1 = 1.0000001,
  pt2 = 1.00000001,
  v3 = 3243.34,
  v4 = "sdfds"
))
#> Warning: Coercing x to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> [1] TRUE

Créé le 2019-07-23 par le package reprex (v0.3.0)

0
Corrado

Si vous préférez ne pas écrire votre propre fonction, essayez check.integer à partir du paquet installr . Actuellement tilise la réponse de VitoshKa.

Essayez aussi check.numeric(v, only.integer=TRUE) à partir du package varhandle , qui présente l'avantage d'être vectorisé.

0
qwr