###二进制转十进制
32位机器上的自然数一共有4294967296个,
如果用一个bit来存放一个整数,1代表存在0代表不存在,那么把全部自然数存储在内存只要4294967296 / (8 * 1024 * 1024) = 512MB(8bit = 一个字节)
而这些自然数存放在文件中,一行一个数字,需要20G的容量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| class BitMap { public static $map = []; //插入值 public static function setValue($value) { $index = self::getIndex($value); if (isset(self::$map[$index])) { self::$map[$index] |= 1 << ($value & 31); } else { self::$map[$index] = 1 << ($value & 31); } /* (1) $value & 31 相当于 $value % 32 , * 这个是取当前的值标示是否存在的位置 * 例如$value = 67 得到3 位置应该是在二进制从右往左数的下标3的位置也就是第四位 * (2) 1 << ($value & 31) 就是 把当前得到的值转化成二进制的位置 * 例如$value = 67 得到3 3的二进制 为11 向左偏移3位 得到2进制 1000 * (3) |= 是 按位或运算并赋值 * 所以当前$map[$index] 的二进制的值为 1000 十进制就是8 */
echo "当前值的二进制:".(decbin($value))."\n"; echo "取模位置左移1:".(decbin(1 << ($value & 31))).'-'.(1 << ($value & 31))."\n"; echo "插入后map:".(decbin(self::$map[$index])).'-'.(self::$map[$index])."\n"; } //查找某个值是否存在 public static function haxValue($value) { $index = self::getIndex($value); if (!isset(self::$map[$index])) { return false; } /** * 例如传入的值为87,bitmap中存的值为67 * (1) 1 << ($value & 31) 得到1<<23 ,1左偏移23位, * 得到 二进制值为 100000000000000000000000 也就是十进制的8388608 * (2) 然后和 self::$map[$index] 进行按位与(二进制1000 和 二进制 100000000000000000000000) * 得到二进制 000000000000000000000000也就是十进制的0 也就是不存在 * 如果存在则返回这个数在self::$map[$index] 中的位置转换成的十进制的值 (如67返回8二进制也就是1000) */ if ((self::$map[$index] & (1 << ($value & 31)))==0) { return false; } return true; }
public static function display() { $keys = array_keys(self::$map); foreach ($keys as $key) { print "map index: {$key}, bit:\n"; $temp = self::$map[$key]; $bit_str = ''; for ($i = 0; $i <= 31; $i++) { $bit_str = (1 & $temp) . $bit_str; echo ($bit_str)."\n"; $temp >>= 1; } echo "{$bit_str}\n"; }
} //去出在数组的第几个key里面 private static function getIndex($value) { return $value >> 5; /** * 相当于floor($value / 32); * 这里是2进制运算当前值右移动5位 * 例如67 二进制为1000011 右移动5位二进制为10 十进制为2 */ } }
$list = [67]; foreach ($list as $value) { BitMap::setValue($value); }
BitMap::display(); var_dump(BitMap::haxValue(87));
|