Fiquei surpreso ao saber que R não vem com uma função útil para verificar se o número é inteiro.
is.integer(66) # FALSE
is.integer(x)
não testa sex
contém números inteiros! Para isso, useround
, como na funçãois.wholenumber(x)
dos exemplos.
O exemplo tem esta função personalizada como uma "solução alternativa"
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
Se eu tivesse que escrever uma função para verificar se há inteiros, presumindo que não li os comentários acima, eu escreveria uma função que teria algo como
check.integer <- function(x) {
x == round(x)
}
Onde minha abordagem falharia? Qual seria o seu trabalho se você estivesse no meu lugar hipotético?
round(x)
for implementado corretamente, o resultado de aplicá-lo a um número inteiro será sempre esse número inteiro ...is.integer
verifica o conceito computacional, acheck.integer
função de usuário verifica o ponto de vista matemático.Respostas:
Outra alternativa é verificar a parte fracionária:
ou, se você quiser verificar dentro de uma certa tolerância:
fonte
x <- 5-1e-8; x%%1
dá 0,9999999 (o que implicaria se,tol==1e-5
por exemplo) que nãox
é um inteiro.min(abs(c(x%%1, x%%1-1))) < tol
invés doabs(min(x%%1, x%%1-1)) < tol
contrário, você obteráFALSE
para qualquer número inteiro ...as.integer(x) == x
? Ele não rejeitará 3 ou 3.0 comois.integer(x)
faria e pegará 3.1.Esta é uma solução usando funções mais simples e sem hacks:
Além do mais, você pode testar um vetor inteiro de uma vez, se desejar. Aqui está uma função:
Você pode alterá-lo para usar
*apply
no caso de vetores, matrizes, etc.fonte
if
else
poderia ser feito de forma simplesisTRUE(test)
. Na verdade, isso é tudo de que você precisa para substituir aif
else
cláusula e asreturn
declarações, pois R retorna automaticamente o resultado da última avaliação.testInteger(1.0000001)
[1] FALSEtestInteger(1.00000001)
[1] TRUEall(a == as.integer(a))
contorna este problema! 'Ler a documentação da linguagem R
as.integer
tem mais a ver com a forma como o número é armazenado do que se ele é praticamente equivalente a um inteiro.is.integer
testa se o número é declarado como um inteiro. Você pode declarar um número inteiro colocando umL
depois dele.Também funções como
round
retornarão um inteiro declarado, que é o que você está fazendox==round(x)
. O problema com essa abordagem é o que você considera ser praticamente um número inteiro. O exemplo usa menos precisão para testar a equivalência.Portanto, dependendo de sua aplicação, você pode ter problemas dessa forma.
fonte
Aqui está uma maneira aparentemente confiável:
Esta solução também permite números inteiros em notação científica:
fonte
check.integer(1e4)
é VERDADEIRO, enquantocheck.integer(1e5)
é FALSO.is.wholenumber
qualquer uma das outras soluções fornecidas em outras respostas. Estes não devem ser diferentes:check.integer(1e22); check.integer(1e23)
. Obviamente, você pode alterar a regex para corrigir isso, mas essa abordagem é terrível. (O comentário vem da atribuição no pacote de instalação.)format(40, scientific = FALSE, digits = 20)
lugar. Eu atualizei a resposta. Obrigado por perceber isso.1.0000000000000001 == 1L [1] TRUE
. Mas minha solução é melhor se você já tiver um número na forma de stringcheck.integer("1000000000000000000000000000000000001") [1] TRUE
Parece que você não vê a necessidade de incorporar alguma tolerância de erro. Não seria necessário se todos os inteiros viessem inseridos como inteiros, no entanto, às vezes eles vêm como resultado de operações aritméticas que perdem alguma precisão. Por exemplo:
Observe que essa não é a fraqueza de R, todos os softwares de computador têm alguns limites de precisão.
fonte
De
Hmisc::spss.get
:opção muito mais segura, IMHO, uma vez que "contorna" o problema de precisão da máquina. Se você tentar
is.integer(floor(1))
, você conseguiráFALSE
. BTW, seu número inteiro não será salvo como número inteiro se for maior que o.Machine$integer.max
valor, que é, por padrão, 2147483647, então altere ointeger.max
valor ou faça as verificações alternativas ...fonte
x <- sqrt(2)^2
, entãoall(floor(x) == x, na.rm = TRUE)
volteFALSE
você pode usar uma condição simples como:
fonte
Em R, se um número é numérico ou inteiro pode ser determinado pela função de classe. Geralmente todos os números são armazenados como numéricos e para definir explicitamente um número como inteiro, precisamos especificar 'L' após o número.
Exemplo:
[1] "numérico"
[1] "inteiro"
Espero que isso seja o que era necessário. Obrigado :)
fonte
[ATUALIZAÇÃO] =================================================== ===============
Com respeito à resposta [ANTIGA] aqui abaixo, descobri que funcionou porque coloquei todos os números em um único vetor atômico; um deles era um personagem, então todos se tornam personagens.
Se usarmos uma lista (portanto, a coerção não ocorre), todos os testes passam corretamente, exceto um
1/(1 - 0.98)
:, que permanece anumeric
. Isso porque otol
parâmetro é por padrão100 * .Machine$double.eps
e esse número está longe de ser50
pouco menos do que o dobro disso. Então, basicamente, para este tipo de números, temos que decidir nossa tolerância!Então, se você quiser que todos os testes se tornem
TRUE
, você podeassertive::is_whole_number(x, tol = 200 * .Machine$double.eps)
De qualquer forma, confirmo que a assertiva IMO continua sendo a melhor solução.
Aqui abaixo uma reprex para este [UPDATE].
Criado em 23/07/2019 pelo pacote reprex (v0.3.0)
[ANTIGO] ===================================================== ==================
IMO a melhor solução vem do
assertive
pacote (que, por enquanto, resolve todos os exemplos positivos e negativos neste tópico):Criado em 23/07/2019 pelo pacote reprex (v0.3.0)
fonte
Se você preferir não escrever sua própria função, tente
check.integer
no instalador do pacote . Atualmente ele usa a resposta de VitoshKa.Experimente também o
check.numeric(v, only.integer=TRUE)
pacote varhandle , que tem a vantagem de ser vetorizado.fonte
Uma vez também pode usar
dplyr::near
:Ele se aplica a qualquer vetor
a
e tem um parâmetro de tolerância opcional.fonte
Não tenho certeza do que você está tentando realizar. Mas aqui estão algumas idéias:
1. Converta para inteiro:
num = as.integer(123.2342)
2. Verifique se uma variável é um inteiro:
is.integer(num)
typeof(num)=="integer"
fonte