使用场景:

  1) 判断奇数偶数

for ($i=; $i <  ; $i++) {
if($i & ){
echo $i.PHP_EOL;
}
}
//输出所有奇数

  2)快速修改状态

$status1 = ;
$status2 = ; echo $status1 ^ ; //
echo $status2 ^ ; //

  3)日常算法

<?php

//普通函数
function ip2int($ip)
{
list($ip1,$ip2,$ip3,$ip4) = explode('.', $ip);
return $ip1*pow(256, 3) + $ip2*pow(256, 2) + $ip3*256 + $ip4;
} //位运算符
function ip2int2($ip)
{
list($ip1,$ip2,$ip3,$ip4) = explode('.', $ip);
return ( $ip1 * (1<<24) ) + ( $ip2 * (1<<16) ) + ( $ip3 * (1<<8) ) + ($ip4);
} $ip = '192.168.0.192'; echo ip2int($ip).PHP_EOL;
echo ip2int2($ip).PHP_EOL;

注意点:有人问,为什么位运算不能直接这样写呢?

function ip2int2($ip)
{
list($ip1,$ip2,$ip3,$ip4) = explode('.', $ip);
return ($ip1<<24) + ($ip2<<16) + ($ip3<<8) + ($ip4);
}

  这样不是更简洁吗?  但是你可以运行一下,会惊讶的发现并不一样

为什么?  需要注意的数值型的上限  http://php.net/manual/zh/language.types.integer.php    可以通过常量 PHP_INT_MAX 来查看这个值的具体大小:   2147483647

应用
需求
这是一个设置消息提醒的功能。我们假设这是一个blog系统,用户希望有人收藏自己的文章后,可以得到一个消息提醒。
这里有三种提醒方式:邮箱提醒、短信提醒、微信公众号提醒,用户可以通过开关按钮控制某种提醒方式是开启还是关闭。可以参考以下表格: 提醒操作 邮箱 短信 微信公众号
文章被收藏 开关按钮 开关按钮 开关按钮
被关注 开关按钮 开关按钮 开关按钮
有人评论 开关按钮 开关按钮 开关按钮
实现
1、数据库设计,表名(remind): 字段 数据类型 默认值
collection(文章被收藏) int default(0)
followed(被关注 ) int default(0)
commented(有人评论) int default(0)
2、在Remind Model中设置执行操作的提醒方式类型: cosnt REMIND_NO = 0;//关闭所有的提醒
cosnt REMIND_EMAIL = 1;//邮箱提醒 2的0次方 转化为二进制是:1
cosnt REMIND_SMS = 2;//短信提醒 2的1次方 转化为二进制是:10
cosnt REMIND_WECHAT = 4;//微信公众号提醒 2的2次方 转化为二进制是:100 如果有新的提醒方式值应为4、8、16,依次类推,2的n次方。 仔细观察二进制转化后 email第一位是1,sms第二位是1,wechat第三位是1.
即email占领了第一位、sms占领了第二位、wechat占领了第三位
1,代表开启提醒;0,代表关闭提醒
如果第一位是1,表示开启邮箱提醒;如果第一位是0,表示关闭邮箱提醒
假设用户希望有人评论他的文章时,收到来自系统的提醒: 只开启邮箱提醒,那数据库中commented字段对应的值应是:1;转化为二进制:1
只开启短信提醒,那数据库中commented字段对应的值应是:2;转化为二进制:10
只开启微信公众号提醒,那数据库中commented字段对应的值应是:4;转化为二进制:100
如果开启邮箱提醒和短信提醒,那数据库中commented字段对应的值应是:1+2=3;转化为二进制:11
如果开启邮箱提醒和微信公众号提醒,那数据库中commented字段对应的值应是:1+4=5;转化为二进制:101
如果开启短信提醒和微信公众号提醒,那数据库中commented字段对应的值应是:2+4=6;转化为二进制:110
如果开启所有提醒,那数据库中commented字段对应的值应是:1+2+4=7;转化为二进制:111
重点来了,前方高能,请注意啦~ 3、控制器中写具体业务逻辑: 用户希望有人关注他后,可以通过邮箱提醒他,所以用户开启了邮箱提醒: 前端传值:['option'=>'followed','type'=>'email'];
后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为0;
email对应的值为1,进行&运算,判断email提醒是否开启
1&0=0,所以未开启,那我们要开启email提醒,此时followed=0+1=1;
后来用户觉得短信提醒比较直接,所以又开启了短信提醒: 前端传值:['option'=>'followed','type'=>'sms'];
后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为1;
sms对应的值为2,进行&运算,判断sms提醒是否开启
2&1=0,所以未开启,那我们要开启sms提醒,此时followed=2+1=3;
后来该用户越来越厉害,每天关注他的人特别多,每天都收到很多消息,所以他又想关闭短信提醒: 前端传值:['option'=>'followed','type'=>'sms'];
后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为3;
sms对应的值为2,进行&运算,判断sms提醒是否开启
2&3=2,所以已开启,那我们要关闭sms提醒,此时followed=3-2=1;
部分程序代码: $option = $GET['option'];//提醒操作,由前端传来的值
$type = $GET['type'];//提醒方式,由前端传来的值
$remind = Remind::model()->find(1);//根据条件,在数据库中找到的一条记录// 如果是提醒方式一
if ($type == "sms") {
if ($remind->$option & Remind::REMIND_SMS) { // true 代表已开启sms提醒,此时应关闭sms提醒
$remind->$option -= Remind::REMIND_SMS;
} else if (!($remind->$option & Remind::REMIND_SMS)) { // false 代表已关闭sms提醒,此时应开启sms提醒
$remind->$option += Remind::REMIND_SMS;
}
}

  

有一个广告表,我们要对广告做显示控制:

手动上下线。

只允许 VIP 查看。

可能的表结构如下:

CREATE TABLE `finger_ad` (
`ad_id` int() unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ad_name` varchar() NOT NULL COMMENT '广告名称',
`ad_image_url` varchar() NOT NULL COMMENT '广告图片',
`ad_url` varchar() NOT NULL COMMENT '广告图片URL跳转地址',
`is_vip` tinyint() NOT NULL DEFAULT '' COMMENT '是否仅限 VIP 显示',
`display` tinyint() NOT NULL DEFAULT '' COMMENT '显示状态:1显示、0隐藏',
PRIMARY KEY (`ad_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='广告表';
假如后期,我们需求更改了。需要再增加几种限制: 已登录用户 未登录用户 天内未登录用户 注册 天的用户 遇到这种限制条件的需求,开发同学是不是很伤脑筋? 可能很多开发第一反应就是在表结构增加这种新增的限制条件字段。一切看来似乎很美好。 的确,这样添加字段是最快最容易的方式。也能完成我们的需求。 但是,这样会引来如下毛病: 每次增加限制条件。我们都要增加字段。这种对数据库的更动能少改就少改。毕竟,无限制的增加字段不可取。 假如广告表数据量很大。大到增加一个字段需要几分钟的时候,这会给数据库服务器造成读写压力。 条件越多,SQL 条件语句就会越来越长。 那么,还有没有更好的方式解决这些问题呢? 答案:有! 这就是我们今天要讲的按位与运算符的高级技巧。 我们把上面的表结构改一下: DROP TABLE IF EXISTS `finger_ad`;
CREATE TABLE `finger_ad` (
`ad_id` int() unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ad_name` varchar() NOT NULL COMMENT '广告名称',
`ad_image_url` varchar() NOT NULL COMMENT '广告图片',
`ad_url` varchar() NOT NULL COMMENT '广告图片URL跳转地址',
`bit_condition` INT() UNSIGNED NOT NULL COMMENT '位运算条件:1-登录可访问、2-未登录可访问、4-30天注册可访问、8-30天未登录可访问、16-未消费可访问、32-VIP可访问',
`display` tinyint() NOT NULL DEFAULT '' COMMENT '显示状态:1显示、0隐藏',
PRIMARY KEY (`ad_id`)
) ENGINE=InnoDB DEFAULT CHARSET UTF8 COMMENT='广告表';
我们把所有的条件都去掉了。增加了一个字段: bit_condition 。把所有的条件都组合到一个字段。 那我们此时该如何写代码呢? 比如,现在要添加如下限制条件的广告: 只允许登录用户访问或已注册 天用户或是 VIP 用户才允许访问该广告。 那么,这个广告的 bit_condition 该如何设置值呢?很简单,把这几个条件的位值直接相加。此时值为:。 很多可能会很奇怪。设置为 ,我怎么知道是这几个值的和呢?如果对 Linux 系统权限熟悉的同学就很容易理解这种做法。实际上,这里运用了按位与运算的特性:任意组合相加的值不会重复。 这个理解起来有一定难度。我三两句也很难给你梳理明白。大家可以在网上深入挖掘一下这方面儿的知识。你只需要知道这一点特点即可。 那么,现在我们该如何写 SQL 呢? 示例如下: SELECT * FROM finger_ad WHERE display = AND bit_condition & = bit_condition
这条 SQL 语句当中的 对应的是当前用户针对这么多条件得到的数值。如果 bit_condition位值是与 按位与与 bit_condition 结果相同,说明条件符合。 我们通过一个字段解决了所有条件的问题。着实得感谢按位与运算符的特性。同时也对 MySQL能支持位运算符感到开心。 那么,它有什么缺点呢? 想必有经验的同学已经看出来了。这种写法只能满足包含关系。假如要实现同时满足 个条件才能访问就不行了。或者,一个满足另外一个取反。 优点明显,同样缺点也很明显。大家要根据实际情况来选用。

PHP之位运算符的更多相关文章

  1. java的布尔运算符和位运算符

    1.布尔运算符 &&  逻辑与: ||   逻辑或: !=  不等于: 三元操作符:?: :表达式为  condition?expression1:expression2(当条件为真时 ...

  2. c 语言的位运算符复习

    转载和修正,原文连接:http://www.cnblogs.com/911/archive/2008/05/20/1203477.html 位运算是指按二进制进行的运算.在系统软件中,常常需要处理二进 ...

  3. Java的算数运算符、关系运算符、逻辑运算符、位运算符

    JAVA的运算符,分为四类: 算数运算符.关系运算符.逻辑运算符.位运算符 算数运算符(9):+  -  *  /  %  ++  -- 关系运算符(6):==  !=  >  >=  & ...

  4. c语言基础表达式, 关系运算符, 逻辑运算符, 位运算符, 数据的取值范围, 分支结构(if...else, switch...case)

    1.表达式: 表达式的判断是有无结果(值), 最简单的表达式是一个常量或变量, 如:12, a, 3 + 1, a + b, a + 5 都是表达式 2.BOOL(布尔)数据类型: c语言中除了基本数 ...

  5. PHP中的运算符---位运算符、递增递减运算符、三元运算符、字符串运算符、数组运算符、类型运算符、错误控制运算符

    1.位运算符 位运算符用来对整型数的指定位进行置位,如果被操作数是字符串,则对该字符串的ASCII码值进行操作. 运算类型 运算符 举例 结果 按位与 & $a & $b 将$a 与 ...

  6. ECMAScript 位运算符

    位运算符是在数字底层(即表示数字的 32 个数位)进行操作的. 重温整数 ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数).在 ECMAScript ...

  7. javascript运算符——位运算符

    × 目录 [1]二进制 [2]非 [3]与[4]或[5]异或[6]左移[7]右移[8]>>>[9]应用 前面的话 位运算符是非常底层的运算,由于其很不直观,所以并不常用.但是,其速度 ...

  8. PHP中为位运算符(几乎很少用)

    PHP语言里的位运算符&.|.^ .~.〈〈 .〉〉 "&" 按位与运算 按位与运算符"&"是双目运算符.其功能是参与运算的两数各对应的 ...

  9. PHP运算符:算数运算符、逻辑运算符、三目运算符、位运算符、字符串运算符。

    赋值运算符 PHP 赋值运算符用于向变量写值. PHP 中基础的赋值运算符是 "=". 这意味着右侧复制表达式会为左侧运算数设置值. _______________________ ...

  10. Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^)

    位运算符主要针对二进制,它包括了:“与”.“非”.“或”.“异或”.从表面上看似乎有点像逻辑运算符,但逻辑运算符是针对两个关系运算符来进行逻辑运算,而位运算符主要针对两个二进制数的位进行逻辑运算.下面 ...

随机推荐

  1. 关于phpstorm ftp目录乱码

    关于IIS FTP服务器汉字文件目录乱码问题:一般来说,IIS 服务器编码默认为GBK,而你的目录可能是UTF-8,将phpstorm的远程连接设置为GBK就OK了.记住服务器的编码,文件的编码要统一

  2. February 13th, 2018 Week 7th Tuesday

    You are your greatest asset. 你就是你自己最大的资本. For most of us, there are few things that we can count on ...

  3. Markdown语法大全

    目录 前言: 1.Markdown基础用法 1.1 目录 1.2 标题 1.3 字体样式 1.4 引用 1.5 图片 1.6 超链接 1.7 列表 1.8 表格 1.9 代码 1.10 流程图 1.1 ...

  4. 08.Python网络爬虫之图片懒加载技术、selenium和PhantomJS

    引入 今日概要 图片懒加载 selenium phantomJs 谷歌无头浏览器 知识点回顾 验证码处理流程 今日详情 动态数据加载处理 一.图片懒加载 什么是图片懒加载? 案例分析:抓取站长素材ht ...

  5. WPF 使用Console.Write打印信息到控制台窗口中

    WPF中使用Console.Write函数来打印信息是没有意义的,因为并没有给其输出字符的窗口.对于桌面程序来说,这是十分合理的,然而有时为了方便调试,在程序编写过程中打印出信息给程序员看还是必要的, ...

  6. [matlab] 6.粒子群优化算法

    粒子群优化(PSO, particle swarm optimization)算法是计算智能领域,除了蚁群算法,鱼群算法之外的一种群体智能的优化算法,该算法最早由Kennedy和Eberhart在19 ...

  7. 【vue】vue +element 搭建项目,Qs用途

    1.安装 (c)npm install qs -S 2.用途 在 axios中,利用QS包装data数据 3.常见用法: import Qs from 'qs'; Qs.stringify(data) ...

  8. springboot获取applicationcontext

    使用springboot之前,我们通过ClassPathXmlApplicationContext加载spring xml配置文件来获取applicationcontext,使用springboot后 ...

  9. 操作循环的关键字switch,break,return的应用及区别

    break 使用break结束循环  break可以终止循环 和 switch语句的运行; break用于结束一个循环,即跳出循环体,执行循环体之后的代码: switch 使用continue提前结束 ...

  10. 输出 1-100 内的奇数和偶数,并对其分别求和(while嵌套if-else循环)

    package com.summer.cn; /** * @author Summer * 输出 1-100 内的奇数和偶数,并对其分别求和 * while嵌套if-else循环 */ public ...