我们在R中处理大数字有哪些数据类型选择?默认情况下,整数的大小似乎是32位,因此来自sql server的bigint数字以及从python通过rpy2传递的任何大数字都会被破坏。
> 123456789123
[1] 123456789123
> 1234567891234
[1] 1.234568e+12
当使用RODBC读取bigint值123456789123456789时,它返回为123456789123456784(参见最后一位数字),并且通过RJSONIO反序列化时的数字相同,返回为-1395630315L(这似乎是RJSONIO的附加错误/限制) )。
> fromJSON('[1234567891]')
[1] 1234567891
> fromJSON('[12345678912]')
[1] -539222976
实际上,我确实需要能够处理来自JSON的大量数据,因此在RJSONIO的限制下,除了找到更好的JSON库(现在看起来像一个非选项)之外,我可能没有解决方法。我想听听专家们对此以及一般情况的看法。
答案 0 :(得分:22)
我理解你的问题与我之前发布的两个人有点不同。
如果R的最大默认值对你来说不够大,你有几个选择(免责声明:我使用了下面提到的每个库,但不是通过R绑定,而是通过其他语言绑定或本机库)
Brobdingnag 包:使用自然日志存储值; (比如Rmpfr,使用R的新类结构实现)。我总是对那些工作需要这种规模的人印象深刻。
library(Brobdingnag)
googol <- as.brob(1e100)
gmp 包:R绑定到古老的GMP(GNU多精度库)。这必须追溯到20年,因为我在大学使用它。这个图书馆的座右铭是“算术无限制”,这是一个可靠的主张 - 整数,有理数,浮点数,等等,直到你盒子上RAM的极限。
library(gmp)
x = as.bigq(8000, 21)
Rmpfr 包:与gmp(上图)和MPFR接口的R绑定,(MPFR反过来是gmp的当代实现。我使用了Python绑定(' bigfloat')并且可以高度推荐。考虑到它的范围,它可能是三者的最佳选择,因为它似乎是最积极维护的,并且最终给出了最全面的文档。
答案 1 :(得分:20)
请参阅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.
所以我建议使用numeric
(即'double') - 一个双精度数字。
答案 2 :(得分:16)
答案 3 :(得分:8)
numeric
类型(应设置为double)。另外需要注意的是,您可能无法取回所有数字。查看数字设置:
> options("digits")
$digits
[1] 7
你可以扩展这个:
options(digits=14)
或者,您可以重新格式化数字:
format(big.int, digits=14)
我测试了你的号码并且得到了相同的行为(即使使用double
数据类型),这可能是一个错误:
> as.double("123456789123456789")
[1] 123456789123456784
> class(as.double("123456789123456789"))
[1] "numeric"
> is.double(as.double("123456789123456789"))
[1] TRUE
答案 4 :(得分:3)
我修复了与rpy2中的整数相关的几个问题(Python可以在需要时从int切换到long,但R似乎无法做到这一点。 整数溢出现在应该返回NA_integer _。
L,
答案 5 :(得分:3)
我试图在最近两天找到这个问题的解决方法,最后我今天找到了它。我们的SQL数据库中有19位长的id,之前我使用RODBC从服务器获取bigint数据。我尝试了int64和bit64,也定义了选项(数字= 19),但RODBC继续提出问题。我用RJDBC替换了RODBC,在从SQL服务器检索bigint数据时,我使用将bigint数据转换为字符串来操纵SQL查询。
以下是示例代码:
#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);
使用这个解决方案,我得到bigint数据而没有任何修改,但它不适用于RODBC。现在SQL服务器与R交互的速度已经受到影响,因为RJDBC比RODBC慢,但也不算太差。
答案 6 :(得分:1)
R可以使用很多选项来获取大数字。您也可以使用as.numeric()。 as.numeric()的问题是我在版本R 3.02的函数中发现了一个错误。如果使用as.numeric()数据类型将数字相乘,并且数字恰好产生大约16位数的结果,则会得到错误结果。 as.numeric()的这个错误已针对许多库进行了测试。
还有另一种选择。
我为R编写了两个程序,一个叫做infiX,另一个是infiXF for R.这个库目前只支持乘法计算。它们都将数字计算为精确的小数。已经测试了100,000次以上。 infiX将以字符串格式处理数字,infiXF将把它带到文件系统库。
将数字存储在内存中时,根据您的内存,限制为8 - 128 Gb。如果编译器不允许您使用所有可用资源,有时甚至更少。在文本文件库中计算数字时,可以计算硬盘大小的1/5。唯一的问题是,计算所需的时间。
例如,如果我计算1TB的数字到另一TB的数字。那是大约2万亿个数字。这在8TB的硬盘驱动器上是可行的。不过,我有时间进行计算吗?
可在此处找到InfiX for R。 http://kevinhng86.iblog.website/2017/02/21/working-with-number-infinity-multiplication-optimised-the-code-r/