ggplot - r y axis scale




Implementierung der nextafter Funktionalität in R (2)

Gibt es irgendeine Implementierung von Funktionalität in R, so dass es möglich ist, die nächste darstellbare Gleitkommazahl von einer gegebenen Gleitkommazahl zu erhalten. Dies wäre ähnlich der nextafter- Funktion in der C-Standardbibliothek. Schemata wie number + .Machine$double.eps funktionieren im Allgemeinen nicht.


Nein, aber es gibt zwei Möglichkeiten, wie Sie es schaffen können:

Verwenden von C

Wenn Sie die genaue Funktionalität der nextafter() -Funktion möchten, können Sie eine C-Funktion schreiben, die als eine Schnittstelle zu der Funktion fungiert, so dass die folgenden zwei Einschränkungen erfüllt sind:

  • Die Funktion gibt keinen Wert zurück. Alle Arbeiten werden als "Nebeneffekt" ausgeführt (Ändern der Werte von Argumenten).
  • Alle Argumente sind Zeiger. Gerade Skalare sind Vektoren (der Länge eins) in R.

Diese Funktion sollte dann als eine gemeinsame Bibliothek kompiliert werden:

R CMD SHLIB foo.c

für UNIX-ähnliche Betriebssysteme. Die gemeinsame Bibliothek kann mit dyn.load("foo.so") aufgerufen werden. Sie können dann die Funktion von innerhalb von R aufrufen, indem Sie die Funktion .C() verwenden

.C("foo", ...)

Eine ausführlichere Behandlung des Anrufens von C von R ist hier .

Verwenden von R

number + .Machine$double.eps ist der Weg zu gehen, aber Sie müssen number + .Machine$double.eps betrachten, wie wenn x - y < .Machine$double.eps oder wenn x == y . Ich würde die Funktion so schreiben:

nextafter <- function(x, y){
  # Appropriate type checking and bounds checking goes here
  delta = y - x
  if(x > 0){
    factor = 2^floor(log2(x)) + ifelse(x >= 4, 1, 0)
      } else if (x < 0) {
    factor = 65
  }
  if (delta > .Machine$double.eps){
    return(x + factor * .Machine$double.eps)
  } else if (delta < .Machine$double.eps){
    return(x - factor * .Machine$double.eps)
  } else {
    return(x)
  }
}

Anders als bei C, wenn Sie ganze Zahlen überprüfen möchten, können Sie dies in derselben Funktion tun, aber Sie müssen das Inkrement je nach Typ ändern.

UPDATE Der vorherige Code hat nicht wie erwartet für Zahlen größer als 2 funktioniert. Es gibt einen Faktor, der mit der .Machine$double.eps multipliziert werden .Machine$double.eps , um ihn groß genug zu machen, damit die Zahlen unterschiedlich sind. Es bezieht sich auf die nächste Potenz von 2 plus eins. Sie können eine Vorstellung davon bekommen, wie das mit dem folgenden Code funktioniert:

n <- -100
factor <- vector('numeric', 100)
for(i in 1:n){
  j = 0
  while(TRUE){
    j = j + 1
    if(i - j * .Machine$double.eps != i) break()
  }
  factor[i] = j
}  

Wenn Sie Rcpp bevorzugen:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double nextAfter(double x, double y) {
   return nextafter(x, y);
}

Dann in R:

sprintf("%.20f", 1)
#[1] "1.00000000000000000000"
sprintf("%.20f", nextAfter(1, 2))
#[1] "1.00000000000000022204"




floating-point