2010-01-12 32 views
23

Những lựa chọn datatype nào chúng ta phải xử lý số lớn trong R? Theo mặc định, kích thước của một số nguyên có vẻ là 32 bit, vì vậy số bigint từ máy chủ sql cũng như bất kỳ số lớn nào được truyền từ python qua rpy2 bị xáo trộn.kiểu dữ liệu tương đương dài/bigint/thập phân trong R

> 123456789123 
[1] 123456789123 
> 1234567891234 
[1] 1.234568e+12 

Khi đọc một giá trị bigint của 123456789123456789 sử dụng RODBC, nó trở lại như 123456789123456784 (xem chữ số cuối cùng), và số lượng tương tự khi deserialized qua RJSONIO, trở lại như -1395630315L (mà có vẻ như một lỗi thêm/giới hạn của RJSONIO).

> fromJSON('[1234567891]') 
[1] 1234567891 
> fromJSON('[12345678912]') 
[1] -539222976 

Trên thực tế, tôi cần để có thể xử lý một số lượng lớn đến từ JSON, như vậy với giới hạn RJSONIO, tôi có thể không có một cách giải quyết trừ cho việc tìm kiếm một JSON thư viện tốt hơn (mà có vẻ như một tổ chức phi tùy chọn đúng hiện nay). Tôi muốn nghe những gì các chuyên gia phải nói về điều này cũng như nói chung.

Trả lời

16

Xem help(integer):

Note that on almost all implementations of R the range of 
representable integers is restricted to about +/-2*10^9: ‘double’s 
can hold much larger integers exactly. 

vì vậy tôi sẽ khuyên bạn sử dụng numeric (ví dụ: 'đúp') - một số đôi chính xác.

+0

Tôi đã xem hàm as.numeric(), nhưng bị nhầm lẫn bởi thực tế là chế độ (1) cũng cung cấp "số" làm loại, vì vậy tôi nghĩ rằng tôi đã xử lý chúng. Sau đó tôi đã thử as.numeric ("123456789123456789") và chỉ thấy một vài con số được in, do đó giả định rằng nó bị mất độ chính xác. Tôi không biết về các tùy chọn ("chữ số") trước đây. – haridsv

+0

Ah, vâng, các chữ số. Ngoài ra, nếu bạn cần số chính xác hoặc số lượng lớn hơn, CRAN có các gói cho ví dụ đó, ví dụ: (có tên là :-) Gói Brobdingnag có số lượng lớn, và cũng có gói gmp để giao tiếp GNU gmp. –

+0

(Tôi biết Dirk biết điều này nhưng tôi bình luận để cảnh báo những người tìm kiếm khác.) Các phiên bản mới hơn của R cho phép chuyển đổi liền mạch sang lưu trữ số nguyên hơn gấp đôi. Kích thước ma trận vẫn không sử dụng chuyển chế độ tự động đó. –

7

Dirk là đúng. Bạn nên sử dụng loại numeric (nên được đặt thành gấp đôi). Điều khác cần lưu ý là bạn có thể không lấy lại tất cả các chữ số. Nhìn vào các thiết lập chữ số:

> options("digits") 
$digits 
[1] 7 

Bạn có thể mở rộng này:

options(digits=14) 

Ngoài ra, bạn có thể định dạng số:

format(big.int, digits=14) 

Tôi đã thử nghiệm số của bạn và đang nhận được hành vi tương tự (thậm chí sử dụng loại dữ liệu double), do đó có thể là lỗi:

> as.double("123456789123456789") 
[1] 123456789123456784 
> class(as.double("123456789123456789")) 
[1] "numeric" 
> is.double(as.double("123456789123456789")) 
[1] TRUE 
+0

Cảm ơn bạn đã chỉ các tùy chọn() và format(), chúng hữu ích. Tuy nhiên, các tùy chọn này dường như chỉ kiểm soát cách số được định dạng để hiển thị, do đó, nó không nên thay đổi cách số được phân tích cú pháp khi sử dụng as.double() hoặc as.numeric(). Hành vi có thể là một lỗi. – haridsv

+0

Tôi không nghĩ rằng các công trình, bạn đang chuyển đổi một số nguyên để tăng gấp đôi và mất độ chính xác, vì vậy bạn sẽ không thể lập chỉ mục trở lại vào một mảng đề cập đến. – evolvedmicrobe

21

Tôi hiểu câu hỏi của bạn hơi khác so với hai người đã đăng trước khi tôi làm.

Nếu giá trị mặc định lớn nhất của R không đủ lớn cho bạn, bạn có một vài lựa chọn (từ chối trách nhiệm: Tôi đã sử dụng từng thư viện mà tôi đề cập dưới đây, chứ không phải thông qua các ràng buộc R, thay vào đó. thư viện)

Gói Brobdingnag: sử dụng nhật ký tự nhiên để lưu trữ giá trị; (như Rmpfr, được triển khai bằng cấu trúc lớp mới của R). Tôi luôn bị ấn tượng bởi bất kỳ ai có công việc đòi hỏi những con số ở quy mô này.

library(Brobdingnag) 

googol <- as.brob(1e100) 

Các gmp gói: R bindings vào GMP đáng kính (GNU Multi-chính xác thư viện). Điều này phải quay trở lại 20 năm vì tôi đã sử dụng nó trong trường đại học. Phương châm của Thư viện này là "Số học không có giới hạn", đó là một tuyên bố đáng tin cậy - số nguyên, lý trí, phao, bất cứ điều gì, ngay đến giới hạn của RAM trên hộp của bạn.

library(gmp) 

x = as.bigq(8000, 21) 

Các Rmpfr gói: bindings R mà giao diện cho cả gmp ​​(trên) và MPFR, (MPFR được trong biến một việc thực hiện hiện đại của gmp Tôi đã sử dụng các bindings Python ('bigfloat') và có thể. Điều này có thể là lựa chọn tốt nhất của bạn trong ba, cho phạm vi của nó, cho rằng nó dường như được duy trì tích cực nhất, và cuối cùng đưa ra những gì dường như là tài liệu kỹ lưỡng nhất. một trong hai người cuối cùng, bạn sẽ cần cài đặt các thư viện gốc, GMPMPFR.

+0

Cảm ơn, nhưng hiện tại tôi hài lòng với những hạn chế của kiểu dữ liệu số, mặc dù nó không thực sự đáp ứng được câu hỏi ban đầu của tôi. Tôi sẽ ghi nhớ ý kiến ​​của bạn và sẽ xem xét chúng trong trường hợp tôi cần xử lý các giá trị lớn hơn. – haridsv

2

Tôi cố định một số vấn đề liên quan đến số nguyên trong rpy2 (Python có thể swich từ int đến lâu khi cần thiết, nhưng R dường như không thể làm điều đó. Luồng tràn số nguyên phải trả lại NA_integer_.

L.

12

Sau khi câu hỏi này được hỏi, các gói int64 Romain Francois và bit64 bởi Jens Oehlschlägel hiện nay có sẵn.

+0

trông giống như int64 đã biến mất – evolvedmicrobe

+1

@evolvedmicrobe chúng tôi sử dụng bit64 trong data.table và nó hoạt động tốt –

2

Tôi đã cố gắng tìm cách giải quyết vấn đề này từ hai ngày qua và cuối cùng tôi đã tìm thấy nó ngay hôm nay. Chúng tôi có 19 chữ số dài ids trong cơ sở dữ liệu SQL của chúng tôi và trước đó tôi đã sử dụng RODBC để có được dữ liệu bigint từ máy chủ. Tôi đã thử int64 và bit64, cũng được xác định tùy chọn (chữ số = 19), nhưng RODBC tiếp tục đưa ra các vấn đề. Tôi đã thay thế RODBC bằng RJDBC và trong khi truy xuất dữ liệu bigint từ máy chủ SQL, tôi đã thao tác truy vấn SQL bằng cách sử dụng dữ liệu đúc bigint thành chuỗi.

Vì vậy, đây là mẫu mã:

#Include stats package 
require(stats); 
library(RJDBC); 
#set the working directory 
setwd("W:/Users/dev/Apps/R/Data/201401_2"); 

#Getting JDBC Driver 
driver <- JDBC("com.microsoft.sqlserver.jdbc.SQLServerDriver", "W:/Users/dev/Apps/R/Data/sqljdbc/enu/sqljdbc4.jar"); 

#Connect with DB 
connection <- dbConnect(driver, "jdbc:sqlserver://DBServer;DatabaseName=DB;", "BS_User", "BS_Password"); 
#Query string 


    sqlText <- paste("SELECT DISTINCT Convert(varchar(19), ID) as ID 
FROM tbl_Sample", sep=""); 

#Execute query 
queryResults <- dbGetQuery(connection, sqlText); 

Với giải pháp này, tôi nhận dữ liệu bigint mà không sửa đổi bất kỳ nhưng nó đã không làm việc với RODBC. Bây giờ tốc độ tương tác máy chủ SQL với R đã bị ảnh hưởng bởi vì RJDBC chậm hơn RODBC nhưng nó không quá tệ.

1

Có nhiều tùy chọn bạn có thể sử dụng cho R cho số lớn. Bạn cũng có thể sử dụng as.numeric(). Vấn đề với as.numeric() là tôi đã tìm thấy một lỗi trong hàm cho phiên bản R 3.02. Nếu bạn nhân các số sử dụng kiểu dữ liệu as.numeric() và các con số xảy ra để tạo ra kết quả dài khoảng 16 chữ số, bạn sẽ nhận được một kết quả lỗi. Lỗi này của as.numeric() đã được thử nghiệm đối với nhiều thư viện.

Có một tùy chọn khác.

Tôi đã viết hai chương trình cho R, một được gọi là infiX và một là infiXF cho R. Thư viện này hiện chỉ hỗ trợ tính toán phép nhân. Cả hai đều tính toán số thập phân chính xác. Đã được kiểm tra 100.000 lần. infiX sẽ xử lý số ở định dạng chuỗi trong đó infiXF sẽ mang nó đến cơ sở hệ thống tệp.

Khi bạn lưu số trong bộ nhớ, bạn bị giới hạn ở mức 8 - 128 Gb phụ thuộc vào bộ nhớ của bạn. Đôi khi thậm chí ít hơn nếu trình biên dịch không cho phép bạn sử dụng tất cả các tài nguyên có sẵn. Khi bạn tính số trên cơ sở tệp văn bản, bạn có thể tính 1/5 kích thước ổ đĩa cứng. Vấn đề duy nhất là, thời gian cần thiết để tính toán.

Ví dụ: nếu tôi đang tính 1 terabyte chữ số cho một terabyte chữ số khác. Đó là khoảng 2 nghìn tỷ chữ số. Đó là doable trên một ổ cứng 8 terabyte. Tuy nhiên, tôi có thời gian để tính toán không?

InfiX for R có thể tìm thấy tại đây.http://kevinhng86.iblog.website/2017/02/21/working-with-number-infinity-multiplication-optimised-the-code-r/

Các vấn đề liên quan