本文属于装糊涂的猪原创,转载请注明出处作者
平时的开发的时候,“进制转换”和“位运算”用的很少,java处理的是高层;在跨平台中用的比较多,如文件读写,数据通信。
“天行健,君子以自强不息。”(乾卦)
“地势坤,君子以厚德载物。”(坤卦)
“随风巽,君子以申命行事。”(巽卦)
“渐雷震,君子以恐惧修省。”(震卦)
“善若水,君子以作事谋始。”(坎卦)
“火同人,君子以类族辨物。”(离卦)
“步泽履,君子以辨民安志。”(兑卦)
“艮山谦,君子以裒多益寡。”(艮卦)
八卦镇楼图.png
阴阳八卦确实可以勉强算作0和1的排列组合,
如果把长横看成0,短横看成1,那上面就相当于:
000(乾 )101(坎 )011(艮 )110(震 )001(巽 )010(离 )111(坤 )100(兑 )
哇!刚好是0、1取三次的全排列组合。既在这个三位数中,每个位有两个选择(0、1),总共有8种组合
受蝙蝠的启发发明了雷达,而不能认为是蝙蝠发明了雷达一样。莱布尼茨受周易八卦的启发发明了二进制,但是这个时候阿Q精神有助于体现出我们的爱国情怀(偷笑)。
一、java进制转换
下图是java提供的各进制之间的转换api,请笑纳:

在本次的蓝牙方面的开发中,我使用到的是Interger.toHexString,主要用于读取蓝牙设备数据,打印出log方便调试,如下。
public static String bytesToHexString(byte[] bytes) {
if (bytes == null) return "";
String result = "";
for (int i = 0; i < bytes.length; i++) {
String hexString = Integer.toHexString(bytes[i] & 0x0FF);
if (hexString.length() == 1) {
hexString = '0' + hexString;
}
result += hexString.toUpperCase();
}
return result;
}
我们知道一个低功耗蓝牙设备可以定义许多 Service, Service 可以理解为一个功能的集合。在 Service 下面,又包括了许多的独立数据项,我们把这些独立的数据项称作 Characteristic。每一个 Characteristic 有一个唯一的 UUID 作为标识符。在 Android 开发中,建立蓝牙连接后,我们说的通过蓝牙发送数据给外围设备就是往这些 Characteristic 中的 Value 字段写入数据;外围设备发送数据给手机就是监听这些 Charateristic 中的 Value 字段有没有变化,如果发生了变化,手机的 BLE API 就会收到一个监听的回调。
int 转 byte
例如 : 现在假如一个characteristic 写入格式为1byte,1byte,1byte,1byte共4Byte的数据时 :
public static byte[] convertInt2Byte(int[] value) {
byte[] ret= new byte[4];
ret[3] = (byte) (value[3] & 0x0FF);
ret[2] = (byte) (value[2] & 0x0FF);
ret[1] =(byte) (value[1] & 0x0FF);
ret[0] = (byte) (value[0] & 0x0FF);
return ret;
}
一个characteristic 写入格式为4byte的数据时 :
public static byte[] convertInt2Byte(int value) {
byte[] ret= new byte[4];
ret[3] = (byte) ((value>> 24) & 0x0FF);
ret[2] = (byte) ((value>> 16) & 0x0FF);
ret[1] = (byte) ((value>> 8) & 0x0FF);
ret[0] = (byte) (value& 0x0FF);
return ret;
}
byte 转 int
当手机读取一个4Byte 的数据时:
public static int convertByte2Int(byte[] b) {
return (b[0] & 0x0FF) + ((b[1] & 0x0FF) << 8) + ((b[2] & 0x0FF) << 16) + ((b[3] & 0x0FF) << 24);
}
那么好,如果手机读取一个characteristic 数据格式为1Byte 4Byte 1Byte 1Byte 1Byte 1Byte共9byte的数据时,该怎么解析呢?
public static int[] convertByte2Int(byte[] b) {
int[] result = new int[6];
result[0] = b[0] & 0x0FF;
result[1] = (b[1] & 0x0FF) + ((b[2] & 0x0FF) << 8) + ((b[3] & 0x0FF) << 16) + ((b[4] & 0x0FF) << 24);
result[2] = b[5] & 0x0FF;
result[3] = b[6] & 0x0FF;
result[4] = b[7] & 0x0FF;
result[5] = b[8] & 0x0FF;
return result;
}
二、位运算
位运算功能强大,下面是在网络上摘录的一些位运算的威力:
功能 | 示例 | 位运算 |
---|---|---|
判断奇数 | 无形在代码中装逼 | (x&1)==1 |
判断偶数 | 无形在代码中装逼 | (x&1)==0 |
去掉最后一位 | (101101->10110) | x >> 1 |
在最后加一个0 | (101101->1011010) | x < < 1 |
在最后加一个1 | (101101->1011011) | x < < 1+1 |
最后一位取反 | (101101->101100) | x ^ 1 |
把右数第k位变成0 | (101101->101001,k=3) | x & ~ (1 < < (k-1)) |
右数第k位取反 | (101001->101101,k=3) | x ^ (1 < < (k-1)) |
取末三位 | (1101101->101) | x & 7 |
取末k位 | (1101101->1101,k=5) | x & ((1 < < k)-1) |
取右数第k位 | (1101101->1,k=4) | x >> (k-1) & 1 |
末k位取反 | (101001->100110,k=4) | x ^ (1 < < k-1) |
把右边连续的1变成0 | (100101111->100100000) | x & (x+1) |
取右边连续的1 | (100101111->1111) | (x ^ (x+1)) >> 1 |
去掉右起第一个1的左边 | (100101000->1000) | x & (x ^ (x-1)) |
在本次的开发中主要使用在了闹钟提醒功能模块中,想想如何实现自定义周一到周末的功能,选定个数不定?如可以只选择周一,亦可以选择周一周二,还可以选择周一到周末...当然可以穷举出所有可能性,每种对应一个int值写入设备,总共也就
如C(1,7)注意1在下,7在上
C(1,7) +C(2,7)+C(3,7)+C(4,7)+C(5,7)+C(6,7)+C(7,7) = 127种,确定要这么玩吗?

Solution
二进制 | 16进制 | |
---|---|---|
周一 (X1) | 00000001 | 0x01 |
周二 (X2) | 00000010 | 0x02 |
周三 (X3) | 00000100 | 0x04 |
周四 (X4) | 00001000 | 0x08 |
周五(X5) | 00010000 | 0x10 |
周六 (X6) | 00100000 | 0x20 |
周日(X7) | 01000000 | 0x40 |
这样当你选择出任意几个出来时,使用或运算( | )连接就可以了,接受到数据用与运算(&)就解析就可以了。 | |
如选择周一,周二:data = X1 | X2, |
当蓝牙设备读取时,判断data&X1>0 ,true即是选择了周一,以此
类推能判断出是否也选择了其他。
以上的解决方案只是抛砖引玉,如果有更好的方案请下方留言。
如果文章对你有帮助,请给作者一个爱心star ,你的鼓励是我坚持写作的动力。

网友评论