Можно ли хранить числа с плавающей запятой с помощью функции perl vec ()? - PullRequest
3 голосов
/ 29 марта 2011

У меня есть Perl-скрипт, который обрабатывает миллионы строк данных о производительности, поэтому мне нужен способ эффективного хранения метрической информации.Я обнаружил в Perl vec() функцию, которая позволяет вам напрямую манипулировать битами строки.Это может быть использовано для имитации массива эффективным способом памяти.

И он отлично работает для хранения целочисленных значений.Но для значений с плавающей запятой это работает не так хорошо.

Вот пример:

#!/usr/bin/perl

my ($s) = '';

vec($s, 0, 32) = 1234;
vec($s, 1, 32) = 12.34;
vec($s, 2, 32) = pack('f', 12.34);

print "1st vec: " . vec($s, 0, 32) . " (should be '1234')\n";
print "2nd vec: " . vec($s, 1, 32) . " (should be '12.34')\n";
print "3rd vec: " . unpack ('f', vec($s, 2, 32)) . " (should be '12.34')\n";

Запуск этого кода на моем компьютере (Mac OS X 10.6.7, perl5.8.9) возвращает следующее:

1st vec: 1234 (should be '1234')
2nd vec: 12 (should be '12.34')
3rd vec:  (should be '12.34')

Как видите, в простом случае perl просто округляет число с плавающей запятой до ближайшего целого числа.Я даже пытался придумать, используя pack() / unpack(), но это просто обнуляет все биты.

Я пробовал еще несколько вариантов, увеличивая количество бит, гуглив вокруг,и т.д. безрезультатно.Похоже, что это должно сработать, поскольку в конце концов все это просто биты.

Спасибо.

1 Ответ

4 голосов
/ 29 марта 2011

vec записывает только целые числа, поэтому 12.34 во втором примере преобразуется в 12. Упакованная строка в третьем примере преобразуется в 0, и при распаковке ('f', 0) происходит сбой.

Одним из решений является запись упакованного значения в виде целого числа,

  vec($s, 2, 32) = unpack('L', pack('f', 12.34));
  print unpack('f', pack('L', vec($s, 2, 32))), "\n";

Однако лучше / быстрее вообще не использовать объезд через vec, а вместо этого использовать версию с 4 аргументами substr, т. Е. Указав (expr, offset, length, replace):

 substr($s, 2*4, 4, pack("f", 12.34));
 print unpack("f", substr($s, 2*4)), "\n";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...