1.用byte枚举代替bool节约空间
C#中bool值占2个字节,而一个字节用byte储存的话可以存下8个bool,还可以让枚举继承其他类型数据储存更多bool值。
参考https://blog.csdn.net/darkrabbit/article/details/82633601
https://blog.csdn.net/darkrabbit/article/details/82666493
大佬讲的很详细,我是菜逼,我能写的都在注释里面了
using UnityEngine;
public enum boolean8 : byte
{
//全部关闭
None=0x00,
//开关1开启的状态 0000 0001
B1 = 0x01,
//开关2开启的状态 0000 0010
B2 = 0x02,
//开关3开启的状态 0000 0100
B3 = 0x04,
//开关4开启的状态 0000 1000
B4 = 0x08,
//开关5开启的状态 0001 0000
B5 = 0x10,
//开关6开启的状态 0010 0000
B6 = 0x20,
//开关7开启的状态 0100 0000
B7 = 0x40,
//开关8开启的状态 1000 0000
B8 = 0x80,
//全部开启
ALL=0xFF,
}
public class Test : MonoBehaviour
{
void Start()
{
boolean8 bools = boolean8.None;
Debug.Log(CheckBool(bools, boolean8.B2));
SetSwitch(ref bools, boolean8.B2,0x01);
Debug.Log(CheckBool(bools, boolean8.B2));
boolean8 checkBools = boolean8.None;
SetSwitch(ref checkBools, boolean8.B1, 0x01);
SetSwitch(ref checkBools, boolean8.B2, 0x01);
SetSwitch(ref checkBools, boolean8.B3, 0x01);
Debug.Log(CheckBools(bools, checkBools, 0x01));
Debug.Log(CheckBools(bools, checkBools, 0x00));
SetSwitch(ref checkBools, boolean8.B2, 0x00);
Debug.Log(CheckBools(bools, checkBools, 0x01));
Debug.Log(CheckBools(bools, checkBools, 0x00));
}
/// <summary>
/// 对某个开关进行控制
/// </summary>
/// <param name="currentBools">当前的布尔组 因为enum是值类型 所以传ref地址进来做修改</param>
/// <param name="boolx">布尔组中的某个开关开启的状态</param>
/// <param name="isOn">设置是否开启0x00表示关闭 0x01表示开启</param>
public void SetSwitch(ref boolean8 currentBools,boolean8 boolx, byte isOn) {
//开启某个开关
if (isOn==0x01)
{
//比如当前开关1111 0000(开启了5,6,7,8号开关),开启2号开关0000 0010, 1111 0000|0000 0010=1111 0010
currentBools |= boolx;
}
//关闭某个开关
else
{
//比如当前开关0000 1111(开启了1,2,3,4号开关),关闭2号开关0000 0010
//先对2号开关取反 ~0000 0010=1111 1101
//对原状态进行与计算 0000 1111&1111 1101 = 0000 1101
currentBools &= ~boolx;
}
}
/// <summary>
/// 检测某个开关是否开启
/// </summary>
/// <param name="currentBools"></param>
/// <param name="boolx"></param>
/// <returns></returns>
public bool CheckBool(boolean8 currentBools,boolean8 boolx) {
//比如当前开关 1101 0101,想获取2号开关是否开启
//1101 0101 & 0000 0010 = 0000 0000
//1101 0110 & 0000 0010 = 0000 0010
return (currentBools & boolx) == boolx;
}
/// <summary>
/// 查询某几个开关的状态
/// </summary>
/// <param name="currentBools">待查询的开关组</param>
/// <param name="checkBools">需要查询的开关组</param>
/// <param name="isAllOn">true表示查询开关是否全部开启,false表示查询开关中是否存在开启</param>
/// <returns></returns>
public bool CheckBools(boolean8 currentBools,boolean8 checkBools,byte isAllOn) {
if (isAllOn==0x01)
{
return (currentBools & checkBools) == checkBools;
}
else
{
return (currentBools & checkBools) != boolean8.None;
}
}
}
测试结果
2.异或交换两个数
这是个很常用的小技巧,不需要第三个数字就可以交换两个数
/// <summary>
/// 交换两个数
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public void Exchange(ref int a, ref int b)
{
//比如a=0000 0001也就是1,b=0000 0010也就是2
a = a ^ b;//a= 0000 0001^0000 0010=0000 0011
b = a ^ b;//b=0000 0011^0000 0010=0000 0001=a
a = a ^ b;//a=0000 0011^0000 0001=0000 0010=b
}
3.左移右移
对于一个数 0000 0001
左移变成 0000 0010相当于*2
同理右移相当于除以2
位运算比乘除法效率高一些
4.相同的数字异或等于0
这个规律某些情况下可以非常高效的解决一些问题
比如一个数组中所有数都是成对出现的,只有一个数除外,如何找到这个数
这是leetcode中的一个经典的题目,答案就是一顿异或,最后相同的数字都会变成0,剩下的就是只出现了一次的数字.