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
Decimal values are referred to as numeric data types in R. This is the default working out data type. If you assign a decimal value for any variable x like given below, x will become a numeric type.
The decimal data type is a machine-independent method that represents numbers of up to 32 significant digits, with valid values in the range 10 -129 - 10 +125. When you define a column with the DECIMAL( p ) data type, it has a total of p (< = 32) significant digits.
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....
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With