2010-01-12 19 views
23

Quali scelte dei tipi di dati dobbiamo gestire i numeri grandi in R? Per impostazione predefinita, la dimensione di un intero sembra essere a 32 bit, quindi i numeri di Bigint dal server SQL così come tutti i numeri grandi passati da python tramite rpy2 vengono manchiati.equivalente a lunghezza/bigint/decimale in R

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

Durante la lettura di un valore bigint di 123.456.789.123,456789 millions usando RODBC, ritorna come 123.456.789.123,456784 millions (vedi l'ultima cifra), e lo stesso numero quando deserializzata via RJSONIO, ritorna come -1395630315L (che sembra un insetto aggiuntivo/limitazione di RJSONIO).

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

In realtà, ho bisogno di essere in grado di gestire grandi numeri provenienti da JSON, quindi con limitazione di RJSONIO, non possono avere una soluzione, tranne per la ricerca di una migliore libreria JSON (che sembra un non-diritto di opzione adesso). Mi piacerebbe sapere cosa hanno da dire gli esperti su questo e in generale.

risposta

16

Vedi 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. 

così mi consiglia di utilizzare numeric (vale a dire 'doppio') - un numero a precisione doppia.

+0

Ho guardato la funzione as.numeric(), ma ero confuso dal fatto che anche la modalità (1) dava "numerico" come tipo, quindi pensavo di averli già a che fare. Ho quindi provato as.numeric ("123456789123456789") e ho visto solo pochi numeri stampati, quindi ho pensato che avesse perso la precisione. Prima non conoscevo le opzioni ("cifre"). – haridsv

+0

Ah, sì, la cosa delle cifre. Inoltre, se hai bisogno di maggiore precisione o numeri grandi, CRAN ha pacchetti per questo come ad es. il (strano nome :-) pacchetto Brobdingnag per grandi numeri, e c'è anche il pacchetto gmp per interfacciare GNU gmp. –

+0

(So che Dirk lo sa, ma sto commentando per avvisare altri utenti.) Le versioni più recenti di R consentono una transizione più semplice allo storage intero come doppi. Tuttavia, la dimensione della matrice non sta ancora utilizzando quella modalità automatica. –

7

Dirk ha ragione. Dovresti utilizzare il tipo numeric (che dovrebbe essere impostato su double). L'altra cosa da notare è che potresti non riuscire a recuperare tutte le cifre. Guarda l'impostazione cifre:

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

È possibile estendere questo:

options(digits=14) 

In alternativa, è possibile riformattare il numero:

format(big.int, digits=14) 

Ho testato il tuo numero e sono sempre lo stesso comportamento (anche utilizzando il tipo di dati double), quindi potrebbe trattarsi di un bug:

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

Grazie per aver indicato le opzioni() e il formato(), sono utili. Tuttavia, queste opzioni sembrano controllare solo il modo in cui il numero è formattato per la visualizzazione, quindi non dovrebbe cambiare il modo in cui il numero viene analizzato mentre si utilizza as.double() o as.numeric(). Il comportamento potrebbe essere un bug. – haridsv

+0

Non penso che funzioni, si converte un numero intero in un doppio e si perde precisione, quindi non si sarà in grado di indicizzare di nuovo in un array a cui si fa riferimento. – evolvedmicrobe

21

Ho capito la tua domanda in modo un po 'diverso rispetto ai due che hanno pubblicato prima di me.

Se il valore predefinito più grande di R non è abbastanza grande per voi, avete alcune scelte (dichiarazione di non responsabilità: ho usato ciascuna delle librerie che menziono di seguito, ma non attraverso le associazioni R, invece attraverso altri collegamenti linguistici o il nativo libreria)

Il Brobdingnag pacchetto: utilizza i registri naturali per memorizzare i valori; (come Rmpfr, implementato usando la nuova struttura di classe di R). Sono sempre impressionato da chiunque il cui lavoro richieda numeri di questa portata.

library(Brobdingnag) 

googol <- as.brob(1e100) 

Il pacchetto gmp: R attacchi al venerabile GMP (libreria GNU Multi-precisione). Questo deve tornare indietro di 20 anni perché l'ho usato nell'università. Il motto di questa libreria è "Aritmetica senza limiti", che è un'affermazione credibile - interi, razionali, float, qualunque cosa, fino ai limiti della RAM sulla tua scatola.

library(gmp) 

x = as.bigq(8000, 21) 

Il Rmpfr pacchetto: collegamenti R che si interfacciano sia GMP (sopra) e MPFR, (MPFR è a sua volta un contemporaneo attuazione del GMP ho utilizzato i binding Python ('bigfloat') e può. Lo consiglio vivamente: potrebbe essere la migliore opzione dei tre, data la sua portata, dato che sembra essere la più attivamente mantenuta e, infine, fornita quella che sembra essere la documentazione più completa

Nota: da usare uno degli ultimi due, è necessario installare le librerie native, GMP e MPFR.

+0

Grazie, ma al momento sono soddisfatto delle limitazioni del tipo di dati numerici, sebbene non abbia realmente soddisfatto la mia domanda originale. Terrò a mente il tuo suggerimento e cercherò di esaminarlo nel caso in cui avessi bisogno di gestire valori più grandi. – haridsv

2

Ho risolto alcuni problemi relativi ai numeri interi in rpy2 (Python può passare da Int a Long quando necessario, ma R sembra non essere in grado di farlo. Gli overflow integer dovrebbero ora restituire NA_integer_.

L.

12

Dopo questa domanda è stato chiesto, pacchetti int64 da Romain Francois e bit64 da Jens Oehlschlägel sono ora disponibili.

+0

sembra che int64 non sia più disponibile – evolvedmicrobe

+1

@evolvedmicrobe usiamo bit64 in data.table e funziona bene –

2

Stavo cercando di trovare una soluzione per questo problema negli ultimi due giorni e finalmente l'ho trovato oggi. Abbiamo 19 identificativi lunghi di cifre nel nostro database SQL e in precedenza ho usato RODBC per ottenere dati bigint dal server. Ho provato int64 e bit64, anche le opzioni definite (cifre = 19), ma RODBC continuava a dare problemi. Ho sostituito RODBC con RJDBC e, mentre recuperavo i dati bigint dal server SQL, ho manipolato la query SQL utilizzando i dati bigint sulla stringa.

ecco codice di esempio:

#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); 

Con questa soluzione, ho ricevuto i dati bigint senza alcuna modifica, ma non ha funzionato con RODBC. La velocità dell'interazione del server SQL con R è stata influenzata dal fatto che RJDBC è più lento di RODBC ma non è così male.

1

Ci sono molte opzioni che è possibile utilizzare per R per il numero grande. Puoi anche usare as.numeric(). Il problema con as.numeric() è che ho trovato un bug nella funzione per la versione R 3.02. Se si moltiplicano i numeri utilizzando il tipo di dati as.numeric() ei numeri si verificano per produrre un risultato di circa 16 cifre, si otterrà un risultato di errore. Questo bug di as.numeric() è stato testato su molte librerie.

C'è un'altra opzione.

Ho scritto due programmi per R, uno è chiamato infiX e l'altro è infiXF per R. Questa libreria attualmente supporta solo il calcolo della moltiplicazione. Entrambi calcolano i numeri al decimale preciso. Testato più di 100.000 volte. infiX tratterà il numero in formato stringa dove infiXF lo porterà alla base del file system.

Quando si memorizza il numero in memoria, il limite di 8 - 128 GB dipende dalla memoria. A volte anche meno se il compilatore non ti consente di utilizzare tutte le risorse disponibili. Quando si calcolano i numeri su una base di file di testo, è possibile calcolare 1/5 della dimensione del disco rigido. L'unico problema è il tempo necessario per un calcolo.

Ad esempio, se stavo calcolando 1 terabyte di cifre su un altro terabyte di cifre. Sono circa 2 trilioni di cifre. È fattibile su un disco fisso da 8 terabyte. Tuttavia, ho il tempo di fare il calcolo?

InfiX per R può essere trovato qui.http://kevinhng86.iblog.website/2017/02/21/working-with-number-infinity-multiplication-optimised-the-code-r/