Me sorprendió saber que R no viene con una función útil para verificar si el número es entero.
is.integer(66) # FALSE
Los archivos de ayuda advierten :
is.integer(x)
¡no prueba six
contiene números enteros! Para eso, useround
, como en la funciónis.wholenumber(x)
en los ejemplos.
El ejemplo tiene esta función personalizada como "solución alternativa"
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
Si tuviera que escribir una función para verificar los números enteros, suponiendo que no haya leído los comentarios anteriores, escribiría una función que iría en la línea de
check.integer <- function(x) {
x == round(x)
}
¿Dónde fallaría mi enfoque? ¿Cuál sería tu trabajo si estuvieras en mi hipotético lugar?
round(x)
se implementa correctamente, el resultado de aplicarlo a un número entero siempre sería ese número entero ...is.integer
comprueba el concepto computacional, lacheck.integer
función de usuario comprueba el punto de vista matemático.Respuestas:
Otra alternativa es verificar la parte fraccionaria:
o, si desea verificar dentro de una cierta tolerancia:
fuente
x <- 5-1e-8; x%%1
da 0.9999999 (lo que implicaría si,tol==1e-5
por ejemplo) que nox
es un número entero.min(abs(c(x%%1, x%%1-1))) < tol
lugar de loabs(min(x%%1, x%%1-1)) < tol
contrario, obtendrásFALSE
cualquier número entero ...as.integer(x) == x
? No rechazará 3 o 3.0 como lois.integer(x)
haría, y detectará 3.1.Aquí hay una solución que usa funciones más simples y sin trucos:
Además, puede probar un vector completo a la vez, si lo desea. Aquí tienes una función:
Puede cambiarlo para usarlo
*apply
en el caso de vectores, matrices, etc.fuente
if
else
podría hacer simplementeisTRUE(test)
. De hecho, eso es todo lo que necesita para reemplazar laif
else
cláusula y lasreturn
declaraciones, ya que R devuelve automáticamente el resultado de la última evaluación.testInteger(1.0000001)
[1] FALSOtestInteger(1.00000001)
[1] VERDADEROall(a == as.integer(a))
soluciona este problema! 'Leer la documentación en lenguaje R
as.integer
tiene más que ver con cómo se almacena el número que si es prácticamente equivalente a un entero.is.integer
comprueba si el número se declara como un entero. Puede declarar un número entero colocando unL
después de él.También funciones como
round
devolverán un entero declarado, que es lo que estás haciendox==round(x)
. El problema con este enfoque es lo que considera que es prácticamente un número entero. El ejemplo usa menos precisión para probar la equivalencia.Entonces, dependiendo de su aplicación, podría tener problemas de esa manera.
fuente
Aquí hay una forma aparentemente confiable:
Esta solución también permite números enteros en notación científica:
fuente
check.integer(1e4)
es VERDADERO, mientras quecheck.integer(1e5)
es FALSO.is.wholenumber
, o cualquiera de las otras soluciones proporcionadas en otras respuestas. Estos no deben ser diferentes:check.integer(1e22); check.integer(1e23)
. Obviamente, puede cambiar la expresión regular para solucionar este problema, pero este enfoque es terrible. (El comentario proviene de la atribución en el paquete de instalación).format(40, scientific = FALSE, digits = 20)
en su lugar. He actualizado la respuesta. Gracias por verlo.1.0000000000000001 == 1L [1] TRUE
. Pero mi solución es mejor si ya obtiene un número en forma de cadenacheck.integer("1000000000000000000000000000000000001") [1] TRUE
Parece que no ve la necesidad de incorporar alguna tolerancia a errores. No sería necesario si todos los enteros vinieran ingresados como enteros, sin embargo, a veces vienen como resultado de operaciones aritméticas que pierden algo de precisión. Por ejemplo:
Tenga en cuenta que esta no es la debilidad de R, todo software de computadora tiene algunos límites de precisión.
fuente
De
Hmisc::spss.get
:opción mucho más segura, en mi humilde opinión, ya que "pasa por alto" el problema de precisión de la máquina. Si lo intenta
is.integer(floor(1))
, lo obtendráFALSE
. Por cierto, su número entero no se guardará como entero si es mayor que el.Machine$integer.max
valor, que es, por defecto, 2147483647, así que cambie elinteger.max
valor o realice las verificaciones alternativas ...fuente
x <- sqrt(2)^2
, entoncesall(floor(x) == x, na.rm = TRUE)
regresaFALSE
Puede usar una condición if simple como:
fuente
En R, la función de clase puede determinar si un número es numérico o entero. Generalmente, todos los números se almacenan como numéricos y para definir explícitamente un número como entero, necesitamos especificar 'L' después del número.
Ejemplo:
[1] "numérico"
[1] "entero"
Espero que esto sea lo que se necesitaba. Gracias :)
fuente
[ACTUALIZAR] ============================================= ===============
Con respecto a la respuesta [VIEJA] aquí abajo, descubrí que funcionaba porque puse todos los números en un solo vector atómico; uno de ellos era un personaje, por lo que todos se convierten en personajes.
Si usamos una lista (por lo tanto, la coerción no ocurre) todas las pruebas pasan correctamente menos una:,
1/(1 - 0.98)
que sigue siendo unnumeric
. Esto se debe a que eltol
parámetro está por defecto100 * .Machine$double.eps
y ese número está lejos de ser un50
poco menos del doble. Entonces, básicamente, para este tipo de números, ¡ tenemos que decidir nuestra tolerancia!Entonces, si desea que todas las pruebas se conviertan
TRUE
, puedeassertive::is_whole_number(x, tol = 200 * .Machine$double.eps)
De todos modos, confirmo que IMO asertivo sigue siendo la mejor solución.
A continuación, un reprex para esta [ACTUALIZACIÓN].
Creado el 2019-07-23 por el paquete reprex (v0.3.0)
[ANTIGUO] ============================================= ==================
En mi opinión, la mejor solución proviene del
assertive
paquete (que, por el momento, resuelve todos los ejemplos positivos y negativos en este hilo):Creado el 2019-07-23 por el paquete reprex (v0.3.0)
fuente
Si prefiere no escribir su propia función, intente
check.integer
desde el instalador de paquetes . Actualmente usa la respuesta de VitoshKa.Pruebe también
check.numeric(v, only.integer=TRUE)
con el paquete varhandle , que tiene la ventaja de estar vectorizado.fuente
Once también puede usar
dplyr::near
:Se aplica a cualquier vector
a
y tiene un parámetro de tolerancia opcional.fuente
No estoy seguro de lo que está tratando de lograr. Pero aquí hay algunas ideas:
1. Convierta a un número entero:
num = as.integer(123.2342)
2. Compruebe si una variable es un número entero:
is.integer(num)
typeof(num)=="integer"
fuente