数値が整数かどうかを確認します


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)...適切に実装され、整数にそれを適用した結果は、常にその整数になります
スティーブン


5
> check.integer(9.0)[1] TRUEそうではありません。
Peng Peng

@ PengPeng、VitoshKaは受け入れられた答えでこれを修正しました。
RomanLuštrik12年

4
整数の数学的および計算の概念について混乱があると思います。関数is.integerは計算の概念をチェックし、check.integerユーザー関数は数学的な観点をチェックします。
ジョアン・ダニエル

回答:


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
ベンボルカー2014年

@BenBolker良いキャッチ、ポジティブな摂動で機能すると思います。私はそれを動作するはずの代替ソリューションに変更しました。
James

2
@ジェームズ、それ以外の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]偽 testInteger(1.00000001)[1]

3
all(a == as.integer(a))この問題を回避します!」
Alex

これは正常に機能していません!次の反例をチェック:frac_test < - 1 /(1から0.98)、all.equal(frac_test、as.integer(frac_test))、isTRUE(all.equal(frac_test、as.integer(frac_test)))
tstudio 2018年

11

R言語のドキュメンテーションを読むas.integerことは、それが整数と実質的に同等である場合よりも、数値がどのように格納されるかと関係があります。is.integer数値が整数として宣言されているかどうかをテストします。L後に整数を宣言することができます。

> 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
2行目は、「as.integerは、数値が整数として宣言されているかどうかをテストします」と述べています。しかし、あなたが「is.integer」を意味していたと私は確信しています。1文字編集なので簡単に変更できませんでした。
PeterVermont 2017年

10

これは、明らかに信頼できる方法の1つです。

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)偽です。
2012

5
-1これはis.wholenumber、または他の回答で提供されている他のソリューションよりも悪いです。これらは異なってはいけません:check.integer(1e22); check.integer(1e23)。あなたは明らかにこれを修正するために正規表現を変更することができますが、このアプローチは恐ろしいです。(コメントは、インストーラーパッケージの帰属に由来します。)
Joshua Ulrich

1
@PatrickT、なるほど。これは、デフォルトの桁の引数です。format(40, scientific = FALSE, digits = 20)代わりに使用してください。答えを更新しました。見つけてくれてありがとう。
VitoshKa

1
@PatrickTあなたはマシン依存の丸めエラーの領域にいます。その点で私の解決策は受け入れられたものと同じ1.0000000000000001 == 1L [1] TRUEです。しかし、すでに文字列形式の数値を取得している場合、私の解決策はより優れていますcheck.integer("1000000000000000000000000000000000001") [1] TRUE
VitoshKa

4
@VitoshKaはあなたの答えを愛しました!見逃した点が1つありますが、小数点のない負の数も整数です;)私はそれに応じてコードを変更しました。
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が得られます。[ところで、それは今までそう参照)2.0の値は、いくつかの小数成分を有することを表すために、Rは初期の計算の結果を提示しないことをイライラさせられる... stackoverflow.com/questions/1535021/...
ジョン

6

からHmisc::spss.get

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

機械精度の問題を「回避」するので、はるかに安全なオプション、IMHO。あなたがしようとするとis.integer(floor(1))、あなたは得るでしょうFALSE。ところで、整数が.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

[更新] =============================================== ===============

以下の[古い]の回答を尊重して、すべての数値を1つの原子ベクトルに入れているため、うまくいったことを発見しました。それらの1つはキャラクターだったので、すべてがキャラクターになります。

:私たちは、リストを使用している場合は、すべてのテストパスを正しくが、1つの(それゆえ、強制は発生しません)1/(1 - 0.98)、残っていますnumeric。これは、tolパラメータがデフォルトで100 * .Machine$double.epsあり、その数がその倍数より50少しも少ないからではないためです。したがって、基本的に、この種の数値について、許容範囲を決定する必要があります。

したがって、すべてのテストをにしたい場合はTRUEassertive::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"


ユーザーが適切な数を入力していることを確認しているだけです。つまり、整数のみの「件名」の数について話しています。
RomanLuštrik2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.