Подтвердить что ты не робот

Long/bigint/десятичный эквивалентный тип данных в R

Какие типы данных мы должны обрабатывать большие числа в R? По умолчанию размер целых чисел составляет 32 бит, поэтому большие числа из sql-сервера, а также любые большие числа, переданные из python через rpy2, становятся искалеченными.

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

При чтении значения bigint 123456789123456789 с использованием RODBC он возвращается как 123456789123456784 (см. последнюю цифру), и тот же номер при десериализации через RJSONIO возвращается как -1395630315L (что кажется дополнительной ошибкой/ограничением RJSONIO).

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

На самом деле, мне нужно иметь возможность обрабатывать большие числа, поступающие из JSON, поэтому с ограничением RJSONIO у меня может не быть обходного пути, кроме как найти лучшую библиотеку JSON (которая сейчас кажется нецелевой). Я хотел бы услышать, что эксперты говорят об этом, а также в целом.

4b9b3361

Ответ 1

См. 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

Я понял ваш вопрос немного иначе, чем те, которые были опубликованы до того, как я это сделал.

Если значение R по умолчанию по умолчанию недостаточно велико, у вас есть несколько вариантов (отказ от ответственности: я использовал каждую из библиотек, о которых я упоминал ниже, но не через привязки R, а не через другие языковые привязки или собственную библиотеку )

Пакет Brobdingnag: использует естественные журналы для хранения значений; (например, Rmpfr, реализованный с использованием новой структуры класса R). Меня всегда поражает любой, чья работа требует таких масштабов.

library(Brobdingnag)

googol <- as.brob(1e100)   

Пакет gmp: привязки R к почтенной GMP (многоточечной библиотеке GNU). Это должно пройти 20 лет, потому что я использовал его в университете. Этот девиз библиотеки - это "Арифметика без ограничений", которая является заслуживающим доверия требованием - целыми числами, рациональностями, плаваниями и т.д., Вплоть до пределов ОЗУ на вашем ящике.

library(gmp)

x = as.bigq(8000, 21)

Пакет Rmpfr: привязки R, которые взаимодействуют как с gmp (выше), так и с MPFR, ( MPFR, в свою очередь, представляет собой современную реализацию gmp. Я использовал привязки Python ( "bigfloat" ) и могу рекомендовать ее высоко. Это может быть вашим лучшим вариантом для трех, учитывая его объем, учитывая, что он наиболее активен поддерживается и, наконец, дается то, что представляется наиболее полной документацией.

Примечание. Чтобы использовать любой из двух последних, вам нужно будет установить собственные библиотеки, GMP и MPFR.

Ответ 3

После этого вопроса были заданы пакеты int64 Ромена Франсуа и bit64 от Jens Oehlschlägel.

Ответ 4

Дирк прав. Вы должны использовать тип 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

Ответ 5

Я исправил несколько проблем, связанных с целыми числами в rpy2 (Python может swich от int до долгого времени, когда это необходимо, но R, похоже, не в состоянии это сделать. Целочисленные переполнения теперь должны возвращать NA_integer _.

L.

Ответ 6

Я пытался найти обходной путь для этой проблемы за последние два дня, и, наконец, я нашел ее сегодня. У нас есть идентификаторы длиной 19 цифр в нашей базе данных SQL, и ранее я использовал RODBC для получения данных bigint с сервера. Я попробовал int64 и bit64, а также определенные параметры (цифры = 19), но RODBC продолжал давать проблемы. Я заменил RODBC на RJDBC, и, получая данные bigint с SQL-сервера, я манипулировал SQL-запросом, используя литье данных bigint в строку.

Итак, вот пример кода:

#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, но это не так уж плохо.

Ответ 7

Есть много вариантов, которые вы можете использовать для R для большого числа. Вы также можете использовать as.numeric(). Проблема с as.numeric() заключается в том, что я нашел ошибку в функции для версии R 3.02. Если вы умножаете числа, используя тип данных as.numeric(), и числа, получившие результат, который составляет около 16 цифр, вы получите результат ошибки. Эта ошибка as.numeric() была протестирована во многих библиотеках.

Есть еще один вариант.

Я написал две программы для R, один называется infiX, а другой - infiXF для R. Эта библиотека в настоящее время поддерживает только вычисление умножения. Оба они вычисляют числа до точного десятичного знака. Испытано 100 000 раз. infiX будет обрабатывать номер в строчном формате, где infiXF перенесет его на базу файловой системы.

Когда вы храните номер в памяти, вы ограничены 8 - 128 Гб в зависимости от вашей памяти. Иногда даже меньше, если компилятор не позволяет использовать все доступные ресурсы. Когда вы вычисляете числа на базе текстового файла, вы можете рассчитать 1/5 от размера жесткого диска. Единственная проблема - время, необходимое для расчета.

Например, если я вычислял 1 терабайт цифр на другой терабайт цифр. Это около 2 триллионов цифр. Это можно сделать на жестком диске емкостью 8 терабайт. Тем не менее, у меня есть время, чтобы сделать расчет?

InfiX для R можно найти здесь. http://kevinhng86.iblog.website/2017/02/21/working-with-number-infinity-multiplication-optimised-the-code-r/