БлогNot. Можно ли работать на PHP с 16-разрядными целыми или упаковываем два в одно

Можно ли работать на PHP с 16-разрядными целыми или упаковываем два в одно

В задаче всплыла необходимость использовать именно 16-разрядные (2-байтовые) целые значения, как на старых платформах. Подойдёт любое онлайн-решение, хоть клиентское, хоть серверное.

Реализация на Javascript вряд ли целесообразна, так как он делает все операнды побитовых операций 32-разрядными целыми.

Что касается PHP, размер целого числа в байтах зависит от конкретной сборки языка и соответствует значению предопределённой константы PHP_INT_SIZE, доступной с версии 5.0.5. Как правило, значение PHP_INT_SIZE - не ниже 4, то есть, те же 32 бита.

Поэтому ничего лучше, чем "упаковывать" по два 16-разрядных (не превышающих 0xFFFF) значения в одно 32-разрядное, я не придумал, вот демка, показывающая как упаковать и распаковать числа:

<?php
 $int1 = 0x00003A3B;
 echo 'Number 1 = '.$int1.' ('.dechex($int1).')';
 $int2 = 0x00006996;
 echo '<br>Number 2 = '.$int2.' ('.dechex($int2).')';
 $packed = $int1 + ($int2<<16);
 echo '<br>Packed number = '.$packed.' ('.dechex($packed).')';
 $int1 = $packed & 65535;
 $int2 = ($packed>>16) & 65535;
 echo '<br>Unpacked numbers = '.$int1.', '.$int2;
?>

Работать это будет только для целых от 0 до 65535 (0x0000FFFF) включительно (проверял на 32-разрядной платформе), отрицательные значения также не поддерживаются.

Тем не менее, во многих задачах можно вдвое сэкономить на размере дампа и/или объёме данных в базе.

В качестве альтернативы можно прочитать бинарные данные в буфер и затем извлекать элементы специально подготовленной функцией, назовём её item:

<?php
 function item($n) {
  global $buf;
  return (ord($buf[$n << 1]) << 8) | ord($buf[$n << 1 | 1]);
 }

 $buf = file_get_contents('data.dat');
 for ($i=0; $i<5; $i++) echo item($i).' ';
 echo '<br>';
 for ($i=0; $i<5; $i++) echo dechex(item($i)).' '; //для проверки, 0x41=65='A' и т.д.
?>

Файл data.dat подготовлен таким кодом:

<?php
 $f = fopen('data.dat', 'w');
 for ($i=65; $i<70; $i++) for ($n=0; $n<2; $n++) fwrite ($f, chr($i), 1);
 fclose ($f);
?>

Полученный файл имеет размер 10 байт и содержит латинские заглавные буквы AABBCCDDEE, которые мы потом интерпретируем как 2-байтовые значения.

Вот выдача скрипта с функцией item:

16705 16962 17219 17476 17733 
4141 4242 4343 4444 4545

28.11.2016, 13:08 [3401 просмотр]


теги: php числа алгоритм

К этой статье пока нет комментариев, Ваш будет первым