2013-06-06 15 views
14

Ho letto i dati memorizzati nel formato DECIMAL da una tabella MySQL. Io voglio fare calcoli su questi numeri entro R.Esiste un tipo di dati "Decimale" in R?

ho usato per gettarli in una represaentation numeri Codice utilizzando as.numeric(), ma la documentazione dice:

numerico è identico a raddoppiare (e reale).

Ma c'è anche un tipo di dati Decimal in R? (Tipo di dati senza errori di arrotondamento, ...)

Ecco un semplice esempio per il problema con errori di arrotondamento:

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

Ciò può essere utile: http://cran.r-project.org/web/packages/Rmpfr/index.html è una libreria per eseguire operazioni in virgola mobile precisione arbitraria in R. –

+0

La documentazione MySQL chiarisce che DECIMAL non è una precisione arbitraria. Permette più cifre (64) di quante possano essere rappresentate in un 'doppio' (53). È inoltre chiaro che il troncamento è previsto se le cifre a destra del punto decimale superano il limite scelto. Sospetto che il troncamento a un particolare limite del doppio potrebbe soddisfare la maggior parte delle esigenze. –

+0

Bel esempio. Ho risolto un problema simile usando 'table()' (qui puoi usare 'table (numbersMirror)'). la tabella sembra arrotondare i numeri. Non ho dettagli su come va, ma per il tuo esempio sembra funzionare. Ad ogni modo: un datatype decimale dovrebbe essere più preciso. (ovviamente solo per operazioni -/+). @DWin: Penso che intendessi 'round()' invece di troncare. –

risposta

5

Si potrebbe creare il proprio:

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

In realtà, alcuni dei pacchetti di grandi numeri possono funzionare anche per questo, dal momento che usano una rappresentazione simile ....

+0

e quindi hai solo bisogno di scrivere metodi per le operazioni aritmetiche di base e quelle non di base che ti servono ... (ma, ottima risposta) – Henrik

+1

@Henrik Sono d'accordo. È un dolore, di sicuro. Il payoff di precisione sarebbe valso la pena per la tua particolare applicazione :-) –

+0

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

0

Un approccio simile alla risposta di Ari ma usando la classe integer64 daPacchetto. L'uso di big int come tipo di dati sottostante per i decimali è pratica comune in varie applicazioni che non supportano il tipo decimale in modo nativo.

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 
Problemi correlati