2010-12-30 13 views
4

Ich würde mich über jede Idee, wie es gemacht wird, freuen, damit wir sie miteinander vergleichen können.Was ist der schnellste Weg zu überprüfen, ob eine Zahl eine positive natürliche Zahl ist? (in R)

ist hier ein beginnen mit:

is.natural <- function(x) 
{ 
    x>0 && identical(round(x), x) 
} 
+0

Ich bin nicht vertraut mit R aber ein bisschen Verschiebung wäre der schnellste. –

+7

Wie wäre es damit? http://stackoverflow.com/questions/3476782/how-to-check-if-the-number-is-integer –

Antwort

5

Die docs deuten auf eine ähnliche Methode, so bezweifle ich, werden Sie noch besser werden. Denken Sie daran, ein Epsilon einzubeziehen, um Genauigkeitsprobleme zu berücksichtigen!

is.naturalnumber <- 
    function(x, tol = .Machine$double.eps^0.5) x > tol & abs(x - round(x)) < tol 
is.naturalnumber(1) # is TRUE 
(x <- seq(1,5, by=0.5)) 
is.naturalnumber(x) #--> TRUE FALSE TRUE ... 
+0

Ich glaube, du meintest das '&&' zu sein ein '&' ... Sonst dein Beispiel doesn ' t Arbeit – hadley

+0

@hadley Fixed, danke. – marcog

+1

schnellste korrekte Lösung –

3

Beachten Sie, dass identical() Kontrollen für Speichertyp auch: Ihre is.natural(1L) kehrt FALSE seit typeof(1L) ist integer aber typeof(round(1L))double ist. Als Alternative zu marcog schlage ich die folgende Funktion, die all.equal() die Prüfung zu tun verwendet und bearbeitet komplexe Zahlen:

is.natural <- function(x, tol = .Machine$double.eps^0.5) { 
    (abs(Im(x)) < tol) && 
    (abs(Re(x)) > tol) && 
    isTRUE(all.equal(x, round(x), 
        tolerance=tol, 
        check.attributes=FALSE, 
        check.names=FALSE)) 
} 
1

Sie müssen zwei Tests: größer als 0 und nahe genug, um eine ganze Zahl. Der identical() - Test schlägt zu oft fehl, weil er auch nach überflüssigen Attributen und dem Speichermodus sucht. Der Zapsmall bietet die Möglichkeit, das Runden auf eine bestimmte Anzahl von Stellen zu beschränken, und zwar auf eine Weise, die auf Vektoren von Kandidatenwerten angewendet werden kann. Sie können die Anzahl der signifikanten Ziffern einstellen, falls gewünscht.

is.natural <- function(x, dig=15){ x > 0 & 
            zapsmall(x, dig) == round(x) & 
            x < .Machine$integer.max } 

x <- (2^0.5)^2 
x ==2 
# [1] FALSE  (machine mathematics) 
is.natural(x) 
# [1] TRUE 

Edit: Ein guter Punkt wurde über die Überprüfung für den Bereich gemacht, so dass hinzugefügt wurde.

2

Eine weitere Lösung ist ein bisschen arithmetics mit:

is.natural2 <- function(x,tol=.Machine$double.eps^0.5){ 
    sign(x) - abs(x-round(x)) >= 1-tol 
} 

Wenn nun alle Lösungen überprüft, es stellte sich heraus, dass das eine von Tal und der von Karakal nicht das richtige Ergebnis gegeben hat:

is.natural <- function(x) 
{ 
    x>0 & identical(round(x), x) 
} 

is.natural2 <- function(x,tol=.Machine$double.eps^0.5){ 
    sign(x) - abs(x-round(x)) >= 1-tol 
} 

is.natural3 <- function(x, dig=15){ x > 0 & zapsmall(x, dig) == round(x) } 


is.natural4 <- function(x,tol=.Machine$double.eps^0.5){ 
    x > 0 & 
    isTRUE(all.equal(x,round(x), 
       tolerance=tol, 
       check.attributes=FALSE, 
       check.names=FALSE)) 
} 

is.naturalnumber <- function(x, tol = .Machine$double.eps^0.5){ 
    x > 0 & abs(x - round(x)) < tol 
} 

Dann:

> X <- (seq(0,3,by=0.5)^0.5)^2 

> is.natural(X) 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE # wrong 

> is.natural2(X) 
[1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE 

> is.natural3(X) 
[1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE 

> is.natural4(X) 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE # wrong 

> is.naturalnumber(X) 
[1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE 

bezüglich Zeitablauf:

> X <- (seq(0,1000000,by=0.5)^0.5)^2 

> system.time(is.natural2(X)) 
    user system elapsed 
    0.24 0.03 0.26 

> system.time(is.natural3(X)) 
    user system elapsed 
    0.67 0.00 0.67 

> system.time(is.naturalnumber(X)) 
    user system elapsed 
    0.22 0.01 0.23 

was macht Marcog zum Gewinner.

2

Sie sollten immer eine ganzzahlige Größenbeschränkung beachten: .Machine$integer.max. Selbst wenn Sie eine Art "Überprüfung" durchführen, wird R, wenn der numerische Wert den Grenzwert überschreitet, als double angezeigt und auf andere Weise gespeichert.

> (x <- as.integer(.Machine$integer.max + 1)) 
[1] NA 
Warning message: 
NAs introduced by coercion 
> (x <- as.double(.Machine$integer.max + 1)) 
[1] 2147483648 
> typeof(x) 
[1] "double" 
> x <- 2147483647L 
> typeof(x) 
[1] "integer" 
> x <- 2147483648L 
Warning message: 
non-integer value 2147483648 qualified with L; using numeric value 
> typeof(x) 
[1] "double" 
+0

+1 für Punkt integer.max, aber ich kann nicht herausfinden, warum Sie sich Sorgen über gerade Ziffern Rundungskonventionen hier. Ich hätte gedacht, dass eine Diskussion der möglichen Fallstricke in Bezug auf die Verwendung von as.integer (die immer eher abschneidet als rundet), relevanter gewesen wäre. –

+0

Guter Punkt ... ignorieren 'runden' Teil! =) – aL3xa

Verwandte Themen