숫자가 정수인지 확인


104

R에 숫자가 정수인지 확인하는 편리한 기능이 없다는 사실에 놀랐습니다.

is.integer(66) # FALSE

도움말 파일은 경고 :

is.integer(x)x 정수 가 포함되어 있는지 테스트하지 않습니다 ! 이를 위해 예제 round의 함수 is.wholenumber(x)에서 와 같이를 사용 하십시오.

이 예제에는 "해결 방법"으로이 사용자 지정 함수가 있습니다.

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

위의 주석을 읽지 않았다고 가정하고 정수를 확인하는 함수를 작성해야한다면,

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

내 접근 방식은 어디에서 실패합니까? 당신이 내 가상의 입장에 있었다면 당신은 어떤 일을 할 것입니까?


round(x)제대로 구현되면 정수에 적용한 결과는 항상 그 정수 가 되었으면 합니다.
— Stephen


5
> check.integer (9.0) [1] TRUE 그렇지 않습니다.
— Peng Peng

@PengPeng, VitoshKa는 수락 된 답변에서 이것을 수정했습니다.
— Roman Luštrik

4
정수의 수학적 및 계산적 개념에 대해 혼란이 있다고 생각합니다. 이 함수 is.integer는 계산 개념을 확인하고 check.integer사용자 함수는 수학적 관점을 확인합니다.
— João Daniel

답변:


126

또 다른 대안은 분수 부분을 확인하는 것입니다.

x%%1==0

또는 특정 허용 오차 내에서 확인하려는 경우 :

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

1
허용 오차 검사 제안이 실제로 작동합니까 ?? 정수 가 아닌x <- 5-1e-8; x%%1 0.9999999 ( tol==1e-5예 : 경우 를 의미 함 )를 제공 합니다. x
— Ben Bolker 2014 년

@BenBolker 좋은 캐치, 내 생각에 긍정적 인 섭동에 대해 작동합니다. 대체 솔루션으로 변경했습니다.
— James

2
@James, 다른 것 min(abs(c(x%%1, x%%1-1))) < tol대신 해야한다고 생각합니다. 정수를 abs(min(x%%1, x%%1-1)) < tol얻을 수 있습니다 FALSE...
— Cath

3
뭐가 문제 야 as.integer(x) == x? 3 또는 3.0을 거부하지 않고 is.integer(x)3.1을 잡을 것입니다.
— Gabi

34

다음은 더 간단한 기능을 사용하고 해킹이없는 솔루션입니다.

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

또한 원하는 경우 전체 벡터를 한 번에 테스트 할 수 있습니다. 다음은 함수입니다.

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

*apply벡터, 행렬 등의 경우에 사용하도록 변경할 수 있습니다 .


11
마지막 if else은 간단히 isTRUE(test). 실제로 R은 마지막 평가의 결과를 자동으로 반환하므로 if else절과 return문 을 교체하는 데 필요한 전부 입니다.
— Gavin Simpson

7
testInteger(1.0000001)[1] FALSE testInteger(1.00000001)[1] TRUE
— PatrickT 2015 년

3
all(a == as.integer(a))이 문제를 해결합니다! '
— 알렉스

이것은 제대로 작동하지 않습니다! 다음의 반례 예를 확인하십시오. frac_test <-1 / (1-0.98), all.equal (frac_test, as.integer (frac_test)), isTRUE (all.equal (frac_test, as.integer (frac_test)))
— tstudio

11

R 언어 문서를 읽는 as.integer것은 실제로 정수와 동일한 경우보다 숫자가 저장되는 방법과 더 관련 이 있습니다. is.integer숫자가 정수로 선언되었는지 테스트합니다. L뒤에 a를 넣어 정수를 선언 할 수 있습니다 .

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

또한 같은 함수 round는 선언 된 정수를 반환합니다 x==round(x). 이 접근 방식의 문제는 실제로 정수라고 생각하는 것입니다. 이 예에서는 동등성을 테스트하기 위해 정밀도가 낮습니다.

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

따라서 응용 프로그램에 따라 그런 식으로 문제가 발생할 수 있습니다.


1
두 번째 줄은 "as.integer는 숫자가 정수로 선언되었는지 테스트합니다."라고 말합니다. 그러나 나는 당신이 "is.integer"를 의미한다고 확신합니다. 한 글자 만 편집해서 쉽게 바꿀 수 없었습니다.
— PeterVermont

10

분명히 신뢰할 수있는 방법은 다음과 같습니다.

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

이 솔루션은 과학적 표기법의 정수도 허용합니다.

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

1
이것은 나에게 그다지 신뢰할 수없는 것 같습니다 : check.integer(1e4)참이고 check.integer(1e5)거짓입니다.
— wch

5
-1 이것은 is.wholenumber, 또는 다른 답변에 제공된 다른 솔루션 보다 나쁩니다 . 달라서는 안됩니다 : check.integer(1e22); check.integer(1e23). 이 문제를 해결하기 위해 정규식을 분명히 변경할 수 있지만이 방법은 끔찍합니다. (코멘트는 installr 패키지의 속성에서 비롯됩니다.)
— 여호수아 울리히

1
@PatrickT, 알겠습니다. 기본 숫자의 인수입니다. 사용하는 format(40, scientific = FALSE, digits = 20)대신. 답변을 업데이트했습니다. 찾아 주셔서 감사합니다.
— VitoshKa

1
@PatrickT 당신은 기계 의존 반올림 오류의 영역에 있습니다. 그 점에서 내 솔루션은 허용 된 솔루션과 동일합니다 1.0000000000000001 == 1L [1] TRUE. 하지만 내 솔루션은 이미 문자열 형식에 숫자를 얻는 경우에 더 낫다check.integer("1000000000000000000000000000000000001") [1] TRUE
— VitoshKa

4
@VitoshKa는 귀하의 답변을 좋아했습니다! 놓친 점이 하나 있지만 소수점이없는 음수도 정수입니다.) 그에 따라 코드를 수정했습니다.
— Mehrad Mahmoudian 2015

8

일부 오류 허용 범위를 통합 할 필요가없는 것 같습니다. 모든 정수가 정수로 입력되면 필요하지 않지만 때로는 정밀도를 잃는 산술 연산의 결과로 제공됩니다. 예를 들면 :

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

이것은 R의 약점이 아니며 모든 컴퓨터 소프트웨어에는 약간의 정밀도 한계가 있습니다.


3
만약 어떤 사람들이 여기서 무슨 일이 일어 났는지 잘 모르겠다면 ... as.integer (2 / 49 * 49)를 입력하면 1 !! [BTW, R이 초기 계산 결과를 2.0으로 표시하지 않아 값에 소수 구성 요소가 있음을 나타냄) 참조 ... stackoverflow.com/questions/1535021/…
— John

6

에서 Hmisc::spss.get:

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

훨씬 더 안전한 옵션 인 IMHO는 기계 정밀도 문제를 "우회"하기 때문입니다. 시도 is.integer(floor(1))하면 FALSE. BTW, 귀하의 정수는 .Machine$integer.max값 보다 크면 정수로 저장되지 않습니다. 기본값은 2147483647이므로 integer.max값을 변경 하거나 대체 검사를 수행하십시오.


1
경우 x <- sqrt(2)^2, 다음 all(floor(x) == x, na.rm = TRUE)반환FALSE
— 코라

3

다음과 같은 간단한 if 조건을 사용할 수 있습니다.

if(round(var) != var)­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­

1

R에서 숫자가 숫자인지 정수인지는 클래스 함수에 의해 결정될 수 있습니다. 일반적으로 모든 숫자는 숫자로 저장되며 숫자를 정수로 명시 적으로 정의하려면 숫자 뒤에 'L'을 지정해야합니다.

예:

x <-1

클래스 (x)

[1] "숫자"

x <-1L

클래스 (x)

[1] "정수"

이것이 필요한 것이기를 바랍니다. 감사 :)


0

[업데이트] ============================================== ===============

아래의 [OLD] 답변에 대해 저는 모든 숫자를 단일 원자 벡터에 넣었 기 때문에 작동한다는 것을 발견했습니다. 그들 중 하나는 캐릭터 였으므로 모두가 캐릭터가됩니다.

목록을 사용하면 (따라서 강제가 발생하지 않음) 모든 테스트가 올바르게 통과되지만 하나 1/(1 - 0.98)는 numeric. 이것은 tol매개 변수가 기본 100 * .Machine$double.eps이고 그 숫자는 50그 두 배보다 조금 작기 때문입니다. 그래서 기본적으로 이런 종류의 숫자에 대해 우리 는 우리의 관용을 결정해야합니다!

그래서 모든 테스트를 원한다면 TRUE 되었으면assertive::is_whole_number(x, tol = 200 * .Machine$double.eps)

어쨌든, 나는 IMO 주장이 최선의 해결 책임을 확인합니다.

여기에이 [UPDATE]에 대한 reprex가 있습니다.

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

reprex 패키지 (v0.3.0)에 의해 2019-07-23에 생성됨

[이전] ============================================= ==================

IMO 최고의 솔루션은 assertive패키지 에서 비롯 됩니다 (현재이 스레드의 모든 긍정적이고 부정적인 예제를 해결합니다).

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

reprex 패키지 (v0.3.0)에 의해 2019-07-23에 생성됨



0

다음을 사용할 수도 있습니다 dplyr::near.

library(dplyr)

near(a, as.integer(a))

모든 벡터에 적용되며 a선택적 허용 오차 매개 변수가 있습니다.


-3

당신이 무엇을 성취하려고하는지 잘 모르겠습니다. 하지만 여기에 몇 가지 생각이 있습니다.
1. 정수로 변환 :
num = as.integer(123.2342)
2. 변수가 정수인지 확인합니다.
is.integer(num)
typeof(num)=="integer"


저는 사용자가 적절한 숫자를 입력했는지 확인하는 것입니다. 우리는 정수일 수있는 "주체"의 수에 대해 이야기하고 있습니다.
— Roman Luštrik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.