R: сериализовать base64 кодировать / декодировать текст не совсем совпадает - PullRequest
3 голосов
/ 25 июня 2010

в моем предыдущем вопросе об использовании serialize () для создания CSV объектов я получил отличный ответ от jmoy, где он рекомендовал кодирование base64 моего сериализованного текста.Это было именно то, что я искал.Как ни странно, когда я пытаюсь применить это на практике, я получаю результаты, которые выглядят правильно, но не совсем соответствуют тому, что я выполнял в процессе сериализации / кодирования.

Пример ниже берет список из 3 векторов и сериализует каждый вектор.Затем каждый вектор кодируется в base64 и записывается в текстовый файл вместе с ключом.Ключ - это просто порядковый номер вектора.Затем я полностью изменяю процесс и читаю каждую строку обратно из CSV.В самом конце вы можете увидеть некоторые предметы, которые не совпадают точно .Это проблема с плавающей запятой?Что-то еще?

require(caTools)

randList <- NULL
set.seed(2)

randList[[1]] <- rnorm(100)
randList[[2]] <- rnorm(200)
randList[[3]] <- rnorm(300)

#delete file contents
fileName <- "/tmp/tmp.txt"
cat("", file=fileName, append=F)

i <- 1
for (item in randList) {
  myLine <- paste(i, ",", base64encode(serialize(item, NULL, ascii=T)), "\n", sep="")
  cat(myLine, file=fileName, append=T) 
  i <- i+1
}

linesIn <- readLines(fileName, n=-1)

parsedThing <- NULL
i <- 1
for (line in linesIn){
  parsedThing[[i]] <- unserialize(base64decode(strsplit(linesIn[[i]], split=",")[[1]][[2]], "raw"))
  i <- i+1
  }

#floating point issue?
identical(randList, parsedThing)

for (i in 1:length(randList[[1]])) {
  print(randList[[1]][[i]] == parsedThing[[1]][[i]])
}

i<-3
randList[[1]][[i]] == parsedThing[[1]][[i]]

randList[[1]][[i]]
parsedThing[[1]][[i]]

Вот сокращенный вывод:

> #floating point issue?
> identical(randList, parsedThing)
[1] FALSE
> 
> for (i in 1:length(randList[[1]])) {
+   print(randList[[1]][[i]] == parsedThing[[1]][[i]])
+ }
[1] TRUE
[1] TRUE
[1] FALSE
[1] FALSE
[1] TRUE
[1] FALSE
[1] TRUE
[1] TRUE
[1] FALSE
[1] FALSE
...
> 
> i<-3
> randList[[1]][[i]] == parsedThing[[1]][[i]]
[1] FALSE
> 
> randList[[1]][[i]]
[1] 1.587845
> parsedThing[[1]][[i]]
[1] 1.587845
> 

Ответы [ 3 ]

2 голосов
/ 25 июня 2010

Хорошо, теперь, когда вы показываете вывод, я могу объяснить вам, что вы делаете (следуя указаниям Павла здесь).

Поскольку это известная проблема (см., Например, эту R FAQ запись ), вам следует пристегнуться и использовать любую из

  • identical()
  • all.equal()
  • функции из пакета RUnit , такие как checkEquals

В итоге, кажется, нет ничего плохого в используемой вами кодировке base64. Вы просто использовали неправильное определение точно . Но, эй, мы экономисты, и все, что меньше триллиона или двух, в любом случае является ошибкой округления ...

2 голосов
/ 26 июня 2010

ascii=T в вашем вызове serialize заставляет R делать неточные двоичные-десятичные-двоичные преобразования при сериализации и десериализации, вызывая различия значений. Если вы удалите ascii=T, вы получите точно такие же числа, как сейчас, это записанное двоичное представление.

base64encode может кодировать необработанные векторы, поэтому ему не нужно ascii=T.

Бинарное представление, используемое serialize, не зависит от архитектуры , поэтому вы можете успешно сериализовать на одной машине и десериализовать на другой.

Ссылка: http://cran.r -project.org / doc / manual / R-ints.html # Сериализация-форматы

2 голосов
/ 25 июня 2010

JD: я запустил ваш фрагмент кода на моем компьютере с Linux, а затем посмотрел на различия, вычисленные randList [[1]] [[i]] - parsedThing [[1]] [[i]].

Да, значения различаются, но только на уровне допуска моей машины с плавающей запятой.Типичная разница была -4,440892e-16, что довольно мало.Некоторые различия были равны нулю.

Меня не удивляет, что сохранение / восстановление представило этот (крошечный) уровень изменений.Любое значимое преобразование данных сопряжено с риском "расшатывания" наименее значимой цифры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...