2013-06-06 37 views
14

Tôi đọc dữ liệu được lưu trữ ở định dạng DECIMAL từ bảng MySQL. Tôi muốn làm các phép tính trên những con số trong vòng R.Có kiểu dữ liệu "Thập phân" trong R không?

tôi sử dụng để đúc chúng vào một represaentation numeri sử dụng as.numeric(), nhưng các tài liệu nói:

số là giống hệt nhau để tăng gấp đôi (và thực tế).

Nhưng cũng có một kiểu dữ liệu thập phân trong R? (Datatype mà không có lỗi làm tròn số, ...)

Dưới đây là một ví dụ đơn giản cho các vấn đề với lỗi làm tròn số:

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

Điều này có thể hữu ích: http://cran.r-project.org/web/packages/Rmpfr/index.html đó là một thư viện để thực hiện hoạt động điểm nổi độc đoán chính xác trong R. –

+0

Tài liệu MySQL làm rõ rằng DECIMAL không phải là độ chính xác tùy ý. Nó cho phép nhiều chữ số (64) hơn có thể được biểu diễn bằng chữ 'double' (53). Nó cũng làm cho rõ ràng rằng cắt ngắn được mong đợi nếu các chữ số ở bên phải của dấu thập phân vượt quá giới hạn đã chọn. Tôi nghi ngờ rằng cắt ngắn đến một giới hạn cụ thể về tăng gấp đôi có thể đáp ứng hầu hết các nhu cầu. –

+0

Ví dụ hay. Tôi đã giải quyết một vấn đề tương tự bằng cách sử dụng 'table()' (ở đây bạn có thể sử dụng 'table (numbersMirror)'). bảng có vẻ làm tròn số. Tôi không có chi tiết về cách nó tròn, nhưng đối với ví dụ của bạn có vẻ như nó hoạt động. Dù sao: một kiểu dữ liệu thập phân phải chính xác hơn. (Tất nhiên chỉ dành cho -/+ hoạt động). @ DWin: Tôi nghĩ bạn có nghĩa là 'round()' thay vì cắt ngắn. –

Trả lời

5

Bạn có thể tạo riêng của bạn:

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

Trên thực tế, một số các các gói số lớn cũng có thể làm việc cho điều này, vì chúng sử dụng một biểu diễn tương tự ....

+0

và sau đó bạn chỉ cần viết các phương thức cho phép toán số học cơ bản và các phương thức phi cơ bản bạn cần ... (nhưng, câu trả lời tuyệt vời) – Henrik

+1

@Henrik Tôi đồng ý. Đó là một nỗi đau, chắc chắn. Tiền chi trả chính xác có giá trị tốt hơn cho ứng dụng cụ thể của bạn :-) –

+0

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

0

Cách tiếp cận tương tự như câu trả lời của Ari nhưng sử dụng integer64 lớp từGói. Sử dụng int lớn như kiểu dữ liệu cơ bản cho thập phân là thực tế phổ biến trong các ứng dụng khác nhau không hỗ trợ kiểu thập phân nguyên bản.

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 
Các vấn đề liên quan