46. 进制
十六进制:
<?php
echo 0x123; // 前面加0x,表示十六进制
echo 1*pow(16, 2)+2*pow(16, 1)+3*pow(16, 0); // 十六进制转十进制
?>
十进制:
<?php
echo 123; // 十进制
echo 1*pow(10, 2)+2*pow(10, 1)+3*pow(10, 0); // 十进制实际算法
?>
八进制:
<?php
echo 0123; // 前面加0,表示八进制
echo 1*pow(8, 2)+2*pow(8, 1)+3*pow(8, 0); // 八进制转十进制
?>
二进制:
<?php
echo 0b10100110; // 前面加0b,表示二进制
echo 1*pow(2, 7)+1*pow(2, 5)+1*pow(2, 2)+1*pow(2, 1); // 二进制转十进制
?>
N进制转十进制公式:
例:N进制的 abc
a * pow(N, M1) + b * pow(N, M2) + c * pow(N, M3)
ps: N为几进制;M为数字所在的位置,从右往左数,从0开始,如a是第2位,则M1为2,依次类推。
题外话:
进制还有一种情况,叫做进制循环,就好比一个圆形重力称,假设最大值为60,当指针显示指向60时,有可能是60,也有可能是0。
那么应该怎么看进制循环呢?
0b11111111 是理解成255,还是-1,取决于程序。
课题案例:
三只老鼠,8瓶药,其中有一瓶有毒,怎么一次性查出那瓶药有毒?
提示:N只老鼠有2^n种可能状态组合。
答:
0 0 1 =》 1
0 1 0 =》 2
0 1 1 =》 3
1 0 0 =》 4
1 0 1 =》 5
1 1 0 =》 6
1 1 1 =》 7
0 0 0 =》 0
4,5,6,7 给老鼠1
2,3,6,7 给老鼠2
1,3,5,7 给老鼠3
若 1,2死,3活,则6号瓶有毒
1,3死,2活,则5号瓶有毒
1死,2,3活,则4号瓶有毒
,,,
依次类推
46. 位运算
位运算,是针对字符上的位来运算。
把位的 0/1 当成 假/真,针对每个位上的逻辑运算,就是位运算。
$a = 0b00001101;
$b = 0b00000011;
操作 二进制 名称 描述
$a & $b 0b00000001 按位与 同真则真,否则为假
$a | $b 0b00001111 按位或 同假则假,否则为真
$a ^ $b 0b00001110 按位异或 不同为真,相同为假
~ $a 0b11110010 按位取反 将 $a 中为 0 的位设为 1,为1的位设为0。
$a >> $b 0b00000001 右移 把$a的位数向右移动$b位,每一次移动相当于除以2
$a << $b 0b01101000 左移 把$a的位数向左移动$b位,每一次移动相当于乘以2
47. 错误报告设置
PHP脚本有N多等级的错误,如:fetal error、notice、warning。
有时候我们不想要显示报错信息,特别是生产环境,因为报错信息可能会暴露服务器的相关信息,会给系统造成重大损失。因此,在开发环境和生产环境设置错误等级报告。
error_reporting(0); // 不报告任何错误
error_reporting(E_ALL); // 报告所有错误
error_reporting(E_ALL ^ E_NOTICE); // 不报告notice
error_reporting(E_ALL & ~ E_NOTICE); // 不报告notice
48. 浮点数并不精确
某些小数在10进制下,是有限的,转成其它进制要无限循环。因此,损失一些精度,导致浮点数的计算和数学上结果不一致。
例:
<?php
// 直接打印八进制
$a = 01.1;
var_dump($a);
// 通过计算: 1 * pow(8, 0) + 1 * pow(8, -1)
var_dump(1 * pow(8, 0) + 1 * pow(8, -1));
?>
49. 逻辑运算的短路特性与运算符优先级
短路特性,是指因某一部分条件不通过,后续的条件不用再做判断,直接跳过。
各个运算符优先级,如下:
优先级 | 结合方向 | 运算符 | 描述 |
---|---|---|---|
1 | 非结合 | clone、new | clone和new |
2 | 左 | [ | array() |
3 | 非结合 | ++ / - - | 递增/递减运算符 |
4 | 非结合 | ~ - (int) (float) (string) (array) (object) (bool) @ | 类型 |
5 | 非结合 | instanceof | 类型 |
6 | 右结合 | ! | 逻辑操作符 |
7 | 左 | * / % | 算术运算符 |
8 | 左 | + - . | 算术运算符和字符串运算符 |
9 | 左 | <<>> | 位运算符 |
10 | 非结合 | < 、<= 、> 、>=、 <> | 比较运算符 |
11 | 非结合 | ==、!=、===、!== | 比较运算符 |
12 | 左 | & | 位运算符和引用 |
13 | 左 | ^ | 位运算符 |
14 | 左 | | | 位运算符 |
15 | 左 | && | 逻辑运算符 |
16 | 左 | || | 逻辑运算符 |
17 | 左 | ? : | 三元运算符 |
18 | 右 | =、+=、-=、*=、/=、.=、%=、&=、|=、^=、 <<=、>>= | 赋值运算符 |
19 | 左 | and | 逻辑运算符 |
20 | 左 | xor | 逻辑运算符 |
21 | 左 | or | 逻辑运算符 |
22 | 左 | , | 多处用到 |
<?php
$a = FALSE;
if($a && $b){
// todo
}
// 点评:
// 若 $a 为假,又用并且计算,结果为假,程序并不会去判断 $b 的真假。
?>
<?php
$a = TRUE;
if($a || $b){
// todo
}
// 点评:
// 若 $a 为真,又用或计算,结果为真,程序并不会去判断 $b 的真假。
?>
课题案例:
$a = 3;
$b = 5;
if($a = 5 || $b = 7)
{
$a++;
$b++;
}
echo $a ,’ ', $b;
手写出$a,$b的值?
50. 文件管理系统
使用PHP代码实现在浏览器读取资源文件。使用函数:opendir()、closedir()、readdir()
index.php
<?php
header('Content-Type: text/html;charset=utf-8');
$path = '.';
if(isset($_GET['dir'])){
$path = $path .'/'. $_GET['dir'];
}else{
$_GET['dir'] = '';
$path .= $_SERVER['REQUEST_URI'];
}
echo $path;
$dh = opendir($path);
if($dh == FALSE){
echo '打开出错';
exit();
}
$list = array();
while(($item = readdir($dh)) != FALSE){
$list[] = $item;
}
closedir($dh);
?>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
</head>
<body>
<h1>文件管理系统</h1>
<table>
<tr>
<td>序号</td>
<td>文件名</td>
<td>操作</td>
</tr>
<tr>
<?php
foreach($list as $k => $v){
echo "<tr>";
echo "<td>$k</td>";
echo "<td>$v</td>";
echo "<td>";
if($v == '.' || $v == '..'){
echo '<a href="index.php?dir='. $_GET['dir'] . $v .'/">浏览</a>';
}else{
if(is_dir($path .'/'. $v)){
echo '<a href="index.php?dir='. $_GET['dir'] . $v .'/">浏览</a>';
}else{
echo '<a href="/'. $_GET['dir'] .'/'. $v .'">查看</a>';
}
}
echo "</td>";
echo "</tr>";
}
?>
</tr>
</table>
</body>
</html>
51. 递归
递归,简单来说就是,函数调用函数本身。
<?php
// 求n以内的所有数相加
function sum($a){
if($a == 1)
return 1;
return $a + sum($a - 1);
}
echo sum(100);
?>
<?php
// 无限级递归
function reclass($data = array(), $pid = 0, $level = 0, $pname = 'parentid'){
$level++;
foreach($data as $v){
if($v[$pname] == $pid){
$v['level'] = $level; // 查询等级
$newdata[] = $v;
$tmp = reclass($data, $v['id'], $level, $pname); // 进入递归
if($tmp){
$newdata = array_merge($newdata, $tmp); // 将数组合并
}
}
}
if(isset($newdata)){
return $newdata;
}
}
?>
52. 递归技巧
假设函数已经完成,需要做跳出处理。
<?php
// 遍历指定目录下的文件及文件夹,以树型展示
function printdir($path, $level = 1){
$dh = opendir($path);
while(($row = readdir($dh)) != FALSE){
if('.' == $row || '..' == $row){
continue;
}
echo '|' , str_repeat('- ', $level) , $row , '<br>';
$tmp = $path .'/'. $row;
if(is_dir($tmp)){
printdir($tmp, ++$level);
}
}
closedir($dh);
}
$path = '.';
printdir($path);
?>
53. 递归与静态变量
staic 特点:在第一次函数调用声明之后存在,且不随函数结束而结束,当函数再次调用时,可以直接利用上次的结果。
<?php
function foo(){
static $a = 10;
$a++;
return $a;
}
echo foo(); // 11
echo foo(); // 12
echo foo(); // 13
?>
<?php
// 对一个多维数组里面的数字进行求和运算
function sum($arr){
static $sum = 0;
foreach($arr as $v){
if(is_array($v)){
sum($v);
}else{
$sum += $v;
}
}
return $sum;
}
$arr = array(1, 2, 3, array(4, array(5, 6, array(7, 8))));
echo sum($arr); // 36
?>
54. 递归练习
-
一个多维数组,如果单元值为数字,则把原来值修改为原来的2倍。
如:array(1, 2, ‘b’, array(3, ‘c’, array(4, 5)));
变成 array(2, 4, ‘b’, array(6, ‘c’, array(8, 10)));// 在做POST、GET安全递归转义时用到
-
递归创建级联目录
如给定多个目录 /a/b/c/d/e/,要求创建目录e,发现找不到目录a,后面无法继续。需要能递归创建。// 项目中经常按 年/月/日 这种格式创建目录,并存在上传文件
-
递归删除目录
如,给定 目录a,要把a目录及所有下级目录全部删除// 后台管理系统中,会批量删除某个目录
-
给定如下分组,完成无限极分类
array(
array(‘id’ => 1, ‘area’ => ‘北京’, ‘pid’ => 0),
array(‘id’ => 2, ‘area’ => ‘河北’, ‘pid’ => 0),
array(‘id’ => 3, ‘area’ => ‘保定’, ‘pid’ => 2),
array(‘id’ => 4, ‘area’ => ‘易县’, ‘pid’ => 3),
array(‘id’ => 5, ‘area’ => ‘海定’, ‘pid’ => 1),
)
55. IP、域名、DNS、host概念
IP,是给每个连接在互联网上的主机分配的一个32位地址,理论上有2^32个
域名,由于IP地址基于数字,不方便记忆,于是便用域名来代替IP地址,域名是一个IP地址的“面具”
DNS,用于记录IP地址和域名之间映射关系的服务
host,本地的域名IP映射
客户端输入域名,向服务器发出请求,首先会到DNS系统进行域名解析,DNS会返回对应的IP地址给客户端,客户端再用此IP地址向服务器发出请求。
浏览器一般都有DNS缓存,访问过一次的域名会将其IP地址缓存到浏览器中,方便下次访问。
如果在host中配了域名到ip的映射,就不会走DNS,而是直接走host。本地优先级最高。