Расхождение в числах с плавающей точкой между NumPy и Clojure / Java - PullRequest
2 голосов
/ 01 февраля 2011

Есть ли у кого-нибудь совет о том, как читать значения с плавающей точкой из двоичного файла, используя Java или Clojure?Я сравниваю свои текущие значения с результатом метода Python NumPy nump.fromfile('path', dtype="f"), и я просто не получаю тот же ответ.Я подозреваю, что это потому, что метод Java DataInputStream.readFloat() предполагает, что двоичный файл был написан Java, а эта документация показывает:

Считывает четыре входных байта и возвращает значение с плавающей запятой,Он делает это, сначала создав значение int точно так же, как метод readInt, затем преобразуя это значение int в float точно так же, как метод Float.intBitsToFloat.Этот метод подходит для чтения байтов, записанных методом writeFloat интерфейса DataOutput.

Итак, я думаю, что java читает значения с плавающей запятой в обратном направлении.Первые двенадцать байтов:

(0 -64 121 -60 0 -64 121 -60 0 -64 121 -60)

Clojure / java видит это как повторное 1.7676097E-38, тогда как NumPy и Python видят это как повторное -999.0.Для справки я использую этот набор данных .

Ответы [ 3 ]

6 голосов
/ 01 февраля 2011

Java использует «сетевой порядок» (big endian) в java.io. Однако java.nio позволяет вам выбрать, какой порядок байтов применить:

user=> (-> (map byte [0 -64 121 -60]) byte-array java.nio.ByteBuffer/wrap 
         (.order java.nio.ByteOrder/LITTLE_ENDIAN) .getFloat)
-999.0

Следующим шагом для вас является либо чтение всего файла в байтовом массиве, либо создание FileChannel из FileInputStream, затем его отображение и чтение из полученного mmaped ByteBuffer с использованием .getFloat.

0 голосов
/ 01 февраля 2011

Похоже, что этот набор данных доступен в формате netCDF.Есть библиотеки netCDF для python + numpy и java.Эти библиотеки решат практически все ваши проблемы с переносимостью и, вероятно, не сильно повлияют на производительность.

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

0 голосов
/ 01 февраля 2011

Вы можете прочитать файл как байты, изменить порядковый номер, записать эти байты в поток в памяти и затем снова использовать DataInputStream, чтобы считать их как числа с плавающей точкой.

...