我有一个循环,通过给出所需的位数来生成所有可能的位组合,问题是当位数超过20时,我的内存已经耗尽,是否有任何可以进行的优化,解决这个问题。
这里是我的代码:
function bitsGenerator($N)
{
$listN = $N;
$bits = ['0', '1'];
//check if input is valid or not
if (!is_int($listN)) {
echo 'Input must be numeric!';
}
if ($listN >= 1 && $listN <= 65) {
if ($listN == 1) {
echo '1';
exit;
}
for ($i = 1; $i <= ($listN - 1); $i++) {
$reverseBits = array_reverse($bits);
$prefixBit = preg_filter('/^/', '0', $bits);
$prefixReverseBits = preg_filter('/^/', '1', $reverseBits);
$bits = array_merge($prefixBit, $prefixReverseBits);
unset($prefixBit, $prefixReverseBits, $reverseBits);
}
$finalBits = array_slice($bits, -$listN);
foreach ($finalBits as $k => $v) {
echo $v . "\n";
}
} else {
echo 'Invalid input!';
}
}
此函数的目的是获取最后$N
组合并显示它们所有其他组合被丢弃,我正在寻找我的代码的某种优化,以便$ bits数组将不存储超过 65 项目,因为最大数量到位因此显示的最大组合数为65.
感谢每一个人帮助我。
答案 0 :(得分:0)
主要问题是保存所有结果的$bits
数组的大小。该数组将包含2 ^ $ N个元素,每个元素的N个长度乘以8位(因为您使用字符串具有前导零),因此您最终将获得大约(2 ^ N)的内存消耗* $ N * 8,即167772160字节。使用RAM时,它不会变小。
$bits
,preg_filter
和array_merge
的工作副本也会占用大量内存。使用$N = 20
运行您的函数会消耗180375552(172MiB)。
unset
变量不会减少消耗的RAM,因为无论如何它们都会在下一次迭代中被覆盖(或者在函数结束时被破坏)
以下函数是我的第一个基于您的函数的草图,使用的RAM少一点:171970560字节或164MiB(对172MiB)。
function myBitsGenerator($length)
{
if (!is_int($length)) {
die('Input must be numeric!');
}
if ($length < 1 || $length > 65) {
die('Input must be between 1 and 65');
}
$bitsArray = ['0', '1'];
$count = 2;
if ($length > 1) {
for ($i = 0; $i < $length; $i++) {
for ($j = 0; $j < $count; $j++) {
$bitsArray[] = $bitsArray[$j] . '1';
$bitsArray[$j] = $bitsArray[$j] . '0';
}
$count += $j;
}
}
$printArray = array_slice($bitsArray, $count - $length);
array_walk(
$printArray,
function ($value) {
echo $value . PHP_EOL;
}
);
}
但是,这些数字的生成过于复杂,应该简化:
理论:二进制数可以用十进制数写,反之亦然。固定长度为$ N的二进制数的可能组合数为x = 2 ^ $N
。从0到x的每个十进制数表示结果中的二进制数。
实际例子 :(二进制)(0b101 === 5)(int)
您只需要用零填充计算的二进制数。
简化的生成器看起来像:
$n = pow(2, $length);
for ($i = 0; $i < $iterations; $i++) {
$binary = str_pad(decbin($i), $length, '0', STR_PAD_LEFT);
}
您可以使用此生成器生成
如果你真的需要使用更少的RAM,你应该考虑将它存储在一个文件中,这会让整个想法变得更慢,但它会减少使用RAM。
function fileBitsGenerator($length)
{
$handle = fopen('bits.txt', 'w+');
$iterations = pow(2, $length);
for ($i = 0; $i < $iterations; $i++) {
fwrite($handle, str_pad(decbin($i), $length, '0', STR_PAD_LEFT) . PHP_EOL);
}
}
这只消耗2097152个字节并进行扩展!
但请注意,性能将取决于您的HDD / SSD速度,并执行大量写入操作(这可能会缩短您的SSD寿命)。例如:如果length = 22