通过位运算,实现单字段标识多个状态位

可能经常有如下这种需求: 需要一张表,来记录学员课程的通过与否. 课程数量不确定,往往很多,且会有变动,随时可能新增一门课.

这种情况下,在设计表结构时,一门课对应一个字段,就有些不合适, 因为不知道课程的具体数量,也无法应对后期课程的增加.

考虑只用一个状态标志位,利用位运算,来标识多门课的通过或否.

这与Linux的文件权限思路一致

Linux文件和目录的权限




设计及实现


  • 左移(<<):

  • 右移(>>):

  • |(或运算):只要当一方为 true 时,结果就是 true,否则为 false。 (有1就为1,全0才为0)

  • &(与运算):只有当两方都为 true 时,结果才是 true,否则为 false。(全1才为1,有0就为0)


对于正数和负数,左移一位就相当于乘以2的1次方,左移n位就相当于乘以2的n次方

如xxxxxx<<2即左移2位,右边空出的位用0填补,高位左移溢出则舍弃该高位


步骤一:


如语文成绩率先出来,我们约定,以这个字段(记为attr)的第一位,来代表该学生语文有没有通过测评(0否1是)


attr为当前该属性字段的值(从数据库里取出来的值). index为约定的第几位来标识当前业务,index从0开始计数


package main

import "fmt"

func main() {

 // 记录阶段
    //如果语文成绩测评通过,调一个写接口,初始attr值为0,约定的表示位置为第1位,又因为从0开始计数,故而index=0

 setRs := set(00//将attr字段的最新值,记录进数据库的attr字段



 // 查询阶段
 //当需要获知该学生的语文是否通过时. 查数据库,获取上面记录进的值(此时setRs即attr=1); 进而get方法,可知道是否通过(如果rs结果为1,则通过)
 rs := get(setRs, 0)
 _ = rs
}

func set(attr, index int) int {
 tmp := 1 << index
    // 1左移0位,即原地没动,还是1
 fmt.Printf("1 << index %d 值为%d:\n", index, tmp)
    // 1 | 0,或运算,有1就为1,故而setRs=1
 setRs := tmp | attr
 fmt.Println(setRs)
 
 return setRs
}

func get(attr, index int) int {
 tmp := attr >> index
    // 1右移0位,即原地不动,还是1
 fmt.Printf("attr %d >> index %d 值为 %d:\n", attr, index, tmp)
 // 0001 & 0001,与运算,全1才为1,故而为0001,即为十进制数1
 getRs := tmp & 1
 fmt.Println(getRs)

 return getRs
}



输出为:

1 << index 0 值为1:
1
attr 1 >> index 0 值为 1:
1

alt

假设孙山语文及格, 张继语文落榜(则不调用写接口,只有通过才调),则二人当前attr的值为1和0.

这样就完成了语文科目的处理




步骤二:


几天后数学测评结果也出来了,继续用attr,约定以这个字段的第二位,来代表该学生数学有没有通过测评(0否1是)


同样用之前的代码,

记录阶段:

package main

import "fmt"

func main() {

 // 记录阶段
    //如果数学成绩测评通过,调写接口,约定的表示位置为第1位,又因为从0开始计数,故而index=1
 // 对于孙山,从数据库取出其attr值,为1; 张继的attr值为0

 // 加入二人都通过了数学测评,都需调用如下写接口

 setRsSun := set(11//将attr字段的最新值,记录进数据库的attr字段
 fmt.Println("-----------")
 setRsZhang := set(01)

}

func set(attr, index int) int {
 tmp := 1 << index
    // 1左移1位,即由"0001"变为"0010",即为十进制数2
 fmt.Printf("1 << index %d 值为%d:\n", index, tmp)
    // 对于语文通过带孙山,0010 | 0001,或运算,有1就为1,故而setRs=0011,即十进制数3
 // 对于语文未通过带张继,0010 | 0000,或运算,有1就为1,全0才为0, 故而setRs=0010,即十进制数2
 setRs := tmp | attr
 fmt.Println(setRs)
 
 return setRs
}


1 << index 1 值为2:
3
-----------
1 << index 1 值为2:
2

alt

查询阶段:


package main

import "fmt"

func main() {


 // 查询阶段
 //当需要获知该学生的语文/数学是否通过时. 查数据库,获取其attr的值; 进而get方法,index字段为该科目约定的位置(语文为1,其index为0; 数学为2,其index为1),即可知道是否通过(如果rs结果为1,则通过)
 sunMath := get(setRsSun, 1//setRsSun=3

 fmt.Println("-----------")
 zhangChinese := get(setRsZhang, 0)//setRsZhang=2


 fmt.Println("sunMath is:",sunMath)
 fmt.Println("zhangChinese is:",zhangChinese)
}


func get(attr, index int) int {
 tmp := attr >> index
   
 
 fmt.Printf("attr %d >> index %d 值为 %d:\n", attr, index, tmp)
 
 getRs := tmp & 1
 fmt.Println(getRs)

 return getRs
}



 // 对于孙山,十进制数3即二进制0011,右移1位,即0001,即十进制数1
attr 3 >> index 1 值为 1:
// 0001 & 0001,与运算,全1才为1,故而为1. 即孙山通过了数学
1
-----------
// 对于张继,十进制数2即二进制0010,右移0位,即原地不动,还是0010,十进制数2
attr 2 >> index 0 值为 2:
// 0010 & 0001,全1才为1,否则为0. 即张继没有通过语文
0

sunMath is: 1
zhangChinese is: 0




步骤三:


过了几天,英语结果也出来了.假如孙山没通过,张继通过,爽哥三门都通过,则有

alt

写入和读取过程同上



步骤四:


假如现在第60个科目'信息技术'的测评出炉, 爽哥前面59门课程全部通过,则attr字段的值为 ,

2的n次方对照表

第60门课'信息技术'也高分通过, 则对于最新的attr值,即 1 << index | attr,

1 << 59 | 576460752303423487 = 1152921504606846975,将这个值计入数据库.


如需获取爽哥有无通过第60门课程,1152921504606846975 >> 59 & 1 = 1,即通过


如果将数据库这个attr字段设置为有符号的bigint类型,则最多可标识 60几个不同业务的状态




更通用的代码:


func main(){

 index := uint8("约定的位置" - 1)
 attr := "来自数据库"

}

func SetAttrBit(attr int, index uint8) int {
 return 1 << index | attr
}


func GetAttrBit(attr int, index uint8) int {
 return attr >> index & 1
}


参考:

用位运算来标识状态




番外


alt

"光学电报"

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/130343.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle笔记-对ROWNUM的一次理解(简单分页)

此博文记录时间&#xff1a;2023-05-05&#xff0c;发到互联网上是2023-10-09 这个在分页里面用得比较多&#xff0c;在MySQL中&#xff0c;通常使用limit去操作&#xff0c;而去感觉比较简单&#xff0c;Oracle中无此关键字。 通过查阅资料后&#xff0c;要实现分页需要用到…

【【萌新的SOC学习之重新起航SOC】】

萌新的SOC学习之重新起航SOC ZYNQ PL 部分等价于 Xilinx 7 系列 FPGA PS端&#xff1a;Zynq 实际上是一个以处理器为核心的系统&#xff0c;PL 部分可以看作是它的一个外设。 我们可以通过使用AXI(Advanced eXtensible Interface)接口的方式调用 IP 核&#xff0c;系统通过 AX…

HTML5+CSS3+JS小实例:仿优酷视频轮播图

实例:仿优酷视频轮播图 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

MFC 鼠标悬停提示框

MFC 鼠标悬停提示框 运行效果 在MFC窗口中添加一个控件 工具栏中拖拽List Box到MFC窗口给List Box添加变量 CListBox m_listbox 增加成员变量 CWnd* m_tip_parent_wnd; CToolTipCtrl m_tip;给m_listbox创建提示框 void create_tip_window(CWnd* tip_wnd, CToolTipCtrl* ti…

Springcloud笔记(2)-Eureka服务注册

Eureka服务注册 服务注册&#xff0c;发现。 在Spring Cloud框架中&#xff0c;Eureka的核心作用是服务的注册和发现&#xff0c;并实现服务治理。 Eureka包含两个组件&#xff1a;Eureka Server和Eureka Client。 Eureka Server提供服务注册服务&#xff0c;各个节点启动后…

C 语言数据类型概述

int 表示基本的整数类型, long, short, unsigned, signed 提供基本整数类型的变式. char 用于指定字符, 也可以表示较小的整数. float, double, long double 表示浮点数. _Bool 表示布尔值 (true 或者 false) _Complex 和 _Imaginary 分别表示复数和虚数. 通过这些关键字创…

stl 输入输出流

标准输入输出流 头文件 iostream 从标准输入读取流 cin >> 从标准输出写入流 cout << get 系列函数 get 无参数&#xff1a;cin.get() 从指定的输入流中提取一个字符&#xff08;包括空白字符&#xff09;&#xff0c;若读取成功&#xff0c;返回该字符的 ASC…

[LeetCode]链式二叉树相关题目(c语言实现)

文章目录 LeetCode965. 单值二叉树LeetCode100. 相同的树LeetCode101. 对称二叉树LeetCode144. 二叉树的前序遍历LeetCode94. 二叉树的中序遍历LeetCode145. 二叉树的后序遍历LeetCode572. 另一棵树的子树 LeetCode965. 单值二叉树 题目 Oj链接 思路 一棵树的所有值都是一个…

分库分表(3)——ShardingJDBC实践

一、ShardingSphere产品介绍 Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈&#xff0c;它由 JDBC、Proxy 和 Sidecar&#xff08;规划中&#xff09;这 3 款相互独立&#xff0c;却又能够混合部署配合使用的产品组成。 它们均提供标准化的数据分…

unity操作_光源组件 c#

准备工作 添加资源导入后先不管&#xff0c;现在主要学习自带Directional Light 我们首先创建一个平面Plane 然后重置一下位置 然后创建一个Cube 也重置一下位置然后修改y0.5刚好在这个平面上 ctrl d复制一个Cube 修改位置和旋转角度 给物体一个颜色 接下来创建一个点光源 我们…

安达发|制造业的新趋势:APS排程软件的广泛应用

近年来&#xff0c;随着科技的快速发展&#xff0c;制造业也在逐步实现智能化、自动化。其中&#xff0c;APS排程软件的应用越来越广泛&#xff0c;成为制造业提高生产效率、降低运营成本的重要工具。本文将深入探讨这一现象背后的原因。 制造业是全球经济的重要支柱&#xff0…

【深度学习】UniControl 一个统一的扩散模型用于可控的野外视觉生成

论文&#xff1a;https://arxiv.org/abs/2305.11147 代码&#xff1a;https://github.com/salesforce/UniControl#data-preparation docker快速部署&#xff1a;https://qq742971636.blog.csdn.net/article/details/133129146 文章目录 AbstractIntroductionRelated WorksUniCo…