Можно ли работать на 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 [3466 просмотров]