问题
I read data stored in the format DECIMAL
from a MySQL-Table. I want to do calculations on those numbers within R.
I used to cast them to a numeri represaentation using as.numeric()
, but the documentation says:
numeric is identical to double (and real).
But is there also a datatype Decimal in R? (Datatype without rounding errors,...)
Here a simple example for the problem with rounding errors:
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
回答1:
You could create your own:
d <- structure( list(i=589L,exp=2L), class="decimal" )
print.decimal <- function( x, ...) print( x$i * 10^(-x$exp) )
> d
[1] 5.89
Actually, some of the big number packages may work for this as well, since they use a similar representation....
回答2:
Similar approach to Ari answer but using integer64
class from bit64
package. Using big int as underlying data type for decimal is common practice in various applications that doesn't support decimal type natively.
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
来源:https://stackoverflow.com/questions/16960167/is-there-a-datatype-decimal-in-r