2013-06-06 8 views
14

Ich lese Daten im Format DECIMAL aus einer MySQL-Tabelle. Ich möchte innerhalb R. Berechnungen auf diese Zahlen tunGibt es in R einen Datentyp "Dezimal"?

habe ich sie zu einem numeri represaentation werfen as.numeric() verwenden, aber die Dokumentation sagt:

numerisch identisch ist zu verdoppeln (und real).

Aber gibt es auch einen Datentyp Dezimal in R? (Datentyp ohne Rundungsfehler, ...)

Hier ist ein einfaches Beispiel für das Problem mit Rundungsfehler:

numbersStrings = c("0.1", "0.9") 
numbersNumeric = as.numeric(numbersStrings) 
numbersMirror = c(numbersNumeric, 1-numbersNumeric) 

str(numbersMirror) 

numbersMirror 
unique(numbersMirror) # has two times 0.1 ... 

sprintf("%.25f", numbersMirror) 
sprintf("%.25f", unique(numbersMirror)) # ... because there was a rounding error 
+0

Dies kann nützlich sein: http://cran.r-project.org/web/packages/Rmpfr/index.html es ist eine Bibliothek beliebiger Genauigkeit Gleitkomma-Operationen in R. auszuführen –

+0

Die MySQL-Dokumentation macht deutlich, dass DECIMAL keine willkürliche Genauigkeit ist. Es erlaubt mehr Ziffern (64), als in einem "doppelten" dargestellt werden können (53). Es wird auch klargestellt, dass eine Kürzung erwartet wird, wenn die Nachkommastellen den gewählten Grenzwert überschreiten. Ich vermute, dass das Abschneiden auf eine bestimmte Grenze für Doppel die meisten Bedürfnisse erfüllen könnte. –

+0

Schönes Beispiel. Ich löste ein ähnliches Problem mit 'table()' (hier könnte man 'table (numbersMirror)') verwenden. Tabelle scheint die Zahlen zu runden. Ich habe keine Details darüber, wie es rund wird, aber für Ihr Beispiel scheint es zu funktionieren. Wie auch immer: ein dezimaler Datentyp sollte genauer sein. (natürlich nur für -/+ Operationen). @DWin: Ich glaube, du meintest 'round()' anstatt zu trunkieren. –

Antwort

5

Sie erstellen könnten Ihre eigenen:

d <- structure(list(i=589L,exp=2L), class="decimal") 
print.decimal <- function(x, ...) print(x$i * 10^(-x$exp)) 
> d 
[1] 5.89 

Eigentlich einige der große Zahlpakete können für dieses ebenso gut arbeiten, da sie eine ähnliche Darstellung verwenden.

+0

und dann müssen Sie nur Methoden für die Grundrechenarten schreiben und die nicht-grundlegenden, die Sie brauchen ... (aber, große Antwort) – Henrik

+1

@Henrik Ich stimme zu. Es ist sicher ein Schmerz. Der Präzisionsgewinn lohnt sich für Ihre spezielle Anwendung besser :-) –

+0

http://cran.r-project.org/web/packages/Brobdingnag/index.html? –

0

Ähnliche Annäherung zu Ari Antwort aber unter Verwendung integer64 Klasse von bit64 Paket. Die Verwendung von Big Int als zugrunde liegenden Datentyp für Dezimalzahlen ist in verschiedenen Anwendungen üblich, die den Dezimaltyp nicht nativ unterstützen.

library(bit64) 

as.decimal = function(x, p=2L) structure(as.integer64(x*10^p), class="decimal", precision=p) 
print.decimal = function(x) print(as.double(x)) 
as.integer64.decimal = function(x) structure(x, class="integer64", precision=NULL) # this should not be exported 
as.double.decimal = function(x) as.integer64(x)/(10^attr(x, "precision")) 
is.decimal = function(x) inherits(x, "decimal") 
"==.decimal" = function(e1, e2) `==`(as.integer64(e1), as.integer64(e2)) 
"+.decimal" = function(e1, e2) `+`(as.integer64(e1), as.integer64(e2)) 

d = as.decimal(12.69) 
is.decimal(d) 
#[1] TRUE 
print(d) 
#[1] 12.69 
as.double(d) 
#[1] 12.69 
d + as.decimal(0.9) 
#[1] 13.59 
0.1 + 0.2 == 0.3 
#[1] FALSE 
as.decimal(0.1) + as.decimal(0.2) == as.decimal(0.3) 
#[1] TRUE 
Verwandte Themen