gpt4 book ai didi

php - 在 PHP 中使用位

转载 作者:可可西里 更新时间:2023-11-01 01:04:13 26 4
gpt4 key购买 nike

假设我想在 PHP 中存储 8 个单词的序列,并且我不想使用压缩。

因为只有 8 个单词,我可以为每个单词分配一个二进制值,然后将这些二进制值而不是 ascii 单词存储在一个文件中。

可能的二进制值是:

000, 001, 010, 011, 100, 101, 110, 111

这会更有效地解析,因为:(1) 现在每个单词的大小都相同,并且 (2) 它占用的空间少得多。

我的问题是:

我如何在 PHP 中执行此操作?我怎样才能为某物分配一个二进制值,然后将其写入文件(按照我想要的方式写入位),然后再次读回?

我想这样做的原因是为了创建一个高效的索引系统。

最佳答案

首先,如果您想压缩数据,请使用 php 内置函数,例如 gzip 扩展..

但正如您所要求的,我已经准备了一个如何在 PHP 中完成此操作的示例。它并不完美,只是一个微不足道的实现。如果我使用每个整数的第 30 位和第 32 位之间的间隙,压缩率可能会更好。也许会添加此功能...但是我使用了 32 位无符号整数来支持字节,因为它们的损失是每 32 位损失 2 位,而不是每字节损失 2 位。

首先我们准备包含关系词=>十进制数的查找表,即编码表:

<?php

// coding table
$lookupTable = array (
// 'word0' => chr(0), // reserved for 0 byte gap in last byte
'word1' => chr(1),
'word2' => chr(2),
'word3' => chr(3),
'word4' => chr(4),
'word5' => chr(5),
'word6' => chr(6),
// reserve one word for white space
' ' => chr(7)
);

然后是压缩函数:

/**
*
*/
function _3bit_compress($text, $lookupTable) {

echo 'before compression : ' . strlen($text) . ' chars', PHP_EOL;

// first step is one byte compression using the lookup table
$text = strtr($text, $lookupTable);
echo 'after one byte per word compression : ' . strlen($text) . ' chars', PHP_EOL;

$bin = ''; // the result
$carrier = 0; // 32 bit usingned int can 'carry' 10 words in 3 bit notation

for($c = 0; $c < strlen($text); $c++) {
$triplet = $c % 10;
// every 30 bits we add the 4byte unsigned integer to $bin.
// please read the manual of pack
if($triplet === 0 && $carrier !== 0) {
$bin .= pack('N', $carrier);
$carrier = 0;
}

$char = $text[$c];
$carrier <<= 3; // make space for the the next 3 bits
$carrier += ord($char); // add the next 3 bit pattern
// echo $carrier, ' added ' . ord($char), PHP_EOL;
}
$bin .= pack('N', $carrier); // don't forget the remaining bits
echo 'after 3 bit compression : ' . strlen($bin) . ' chars', PHP_EOL;
return $bin;
}

以及解压函数:

/**
*
*/
function _3_bit_uncompress($compressed, $lookupTable) {
$len = strlen($compressed);
echo 'compressed length: : ' . $len . ' chars', PHP_EOL;

$i = 0;
$tmp = '';
$text = '';
// unpack string as 4byte unsigned integer
foreach(unpack('N*', $compressed) as $carrier) {
while($i < 10) {
$code = $carrier & 7; // get the next code
// echo $carrier . ' ' . $code, PHP_EOL;
$tmp = chr($code) . $tmp;
$i++;
$carrier >>= 3; // shift forward to the next 3 bits
}
$i = 0;
$text = $text . $tmp;
$tmp = '';
}
// reverse translate from decimal codes to words
return strtr($text, array_flip($lookupTable));
}

现在是测试功能的时候了:)

$original = <<<EOF
word1 word2 word3 word4 word5 word6 word1 word3 word3 word2
EOF;


$compressed = _3bit_compress($original, $lookupTable);
$restored = _3_bit_uncompress($compressed, $lookupTable);

echo 'compressed size: ' . round(strlen($compressed) * 100 / strlen($original), 2) . '%', PHP_EOL;

echo 'Message before compression : ' . $original, PHP_EOL;
echo 'Message after decompression : ' . $restored, PHP_EOL;

这个例子应该给你:

before compression                  : 60 chars
after one byte per word compression : 20 chars
after 3 bit compression : 8 chars
compressed length: : 8 chars
compressed size: 13,33%
Message before compression : word1 word2 word3 word4 word5 word6 word1 word3 word3 word2
Message after decompression : word1 word2 word3 word4 word5 word6 word1 word3 word3 word2

如果我们用长词进行测试,压缩率当然会变得更好:

before compression                  : 112 chars
after one byte per word compression : 16 chars
after 3 bit compression : 8 chars
compressed length: : 8 chars
compressed size: 7,14%
Message before compression : wooooooooord1 wooooooooord2 wooooooooord2 wooooooooord3 wooooooooord1 wooooooooord2 wooooooooord2 wooooooooord3
Message after decompression : wooooooooord1 wooooooooord2 wooooooooord2 wooooooooord3 wooooooooord1 wooooooooord2 wooooooooord2 wooooooooord3

关于php - 在 PHP 中使用位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15108768/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com