Tips

iOS 进制和位运算的应用

2018-03-29  本文已影响24人  TT_IT有故事的程序员

进制

进制也就是进位制,是人们规定的一种进位方法。 对于任何一种进制—X进制,就表示某一位置上的数运算时是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。

进制转换

1、二进制转十进制

方法:二进制数从低位到高位(即从右往左)计算,第0位的权值是2的0次方,第1位的权值是2的1次方,第2位的权值是2的2次方,依次递增下去,把最后的结果相加的值就是十进制的值了。

例:将二进制的(101011)B转换为十进制的步骤如下:

  1. 第0位 1 x 2^0 = 1;

  2. 第1位 1 x 2^1 = 2;

  3. 第2位 0 x 2^2 = 0;

  4. 第3位 1 x 2^3 = 8;

  5. 第4位 0 x 2^4 = 0;

  6. 第5位 1 x 2^5 = 32;

  7. 读数,把结果值相加,1+2+0+8+0+32=43,即(101011)B=(43)D。


2、八进制转十进制

八进制 → 十进制
方法:八进制数从低位到高位(即从右往左)计算,第0位的权值是8的0次方,第1位的权值是8的1次方,第2位的权值是8的2次方,依次递增下去,把最后的结果相加的值就是十进制的值了。
八进制就是逢8进1,八进制数采用 0~7这八数来表达一个数。

例:将八进制的(53)O转换为十进制的步骤如下:

  1. 第0位 3 x 8^0 = 3;

  2. 第1位 5 x 8^1 = 40;

  3. 读数,把结果值相加,3+40=43,即(53)O=(43)D。


3、十六进制转十进制

方法:十六进制数从低位到高位(即从右往左)计算,第0位的权值是16的0次方,第1位的权值是16的1次方,第2位的权值是16的2次方,依次递增下去,把最后的结果相加的值就是十进制的值了。
十六进制就是逢16进1,十六进制的16个数为0123456789ABCDEF。

例:将十六进制的(2B)H转换为十进制的步骤如下:

  1. 第0位 B x 16^0 = 11;

  2. 第1位 2 x 16^1 = 32;

  3. 读数,把结果值相加,11+32=43,即(2B)H=(43)D。


4、十进制转二进制

方法:除2取余法,即每次将整数部分除以2,余数为该位权上的数,而商继续除以2,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为止,最后读数时候,从最后一个余数读起,一直到最前面的一个余数。

例:将十进制的(43)D转换为二进制的步骤如下:

  1. 将商43除以2,商21余数为1;

  2. 将商21除以2,商10余数为1;

  3. 将商10除以2,商5余数为0;

  4. 将商5除以2,商2余数为1;

  5. 将商2除以2,商1余数为0;

  6. 将商1除以2,商0余数为1;

  7. 读数,因为最后一位是经过多次除以2才得到的,因此它是最高位,读数字从最后的余数向前读,101011,即(43)D=(101011)B。
    ......
    暂时关于进制就介绍到这里。

iOS 中的位运算

先来看一段代码:

UNNotificationPresentationOptionBadge|
UNNotificationPresentationOptionSound|
UNNotificationPresentationOptionAlert

这是在做做APNS推送时有用到,需要设置推送的提醒方式,这里的意思是,提醒方式为:徽标或声音或提示框。我们尝试打印一下:

NSLog(@"%lu",UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound| UNNotificationPresentationOptionAlert)

输出的结果是 7,来看看是为什么?

typedef NS_OPTIONS(NSUInteger, UNNotificationPresentationOptions) {
    UNNotificationPresentationOptionBadge   = (1 << 0),
    UNNotificationPresentationOptionSound   = (1 << 1),
    UNNotificationPresentationOptionAlert   = (1 << 2),
} __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

UNNotificationPresentationOptionBadge = (1 << 0) : 表示00000001左移0位 = 00000001

UNNotificationPresentationOptionSound = (1 << 1):表示00000001左移1位 = 00000010

UNNotificationPresentationOptionAlert = (1 << 2) :表示00000001左移2位 = 00000100

左移运算符 <<
公式 x << 3 就是把x的各二进位左移3位
1<<1 实际就是 0001 << 1 = 0010 转成十进制后就是 2
1<<4 实际就是 0001 << 4 = 10000 转成十进制后就是 16

|是或运算符,也就是:00000001 | 00000010 | 00000100 = 00000111 = 4 + 2 + 1 = 7,
只要对应的二个二进位有一个为1时,结果位就为1

&与运算符 ,也就是: 00000001 & 00000010 & 00000100 = 00000000 = 0,
只有对应的二个二进位都为1时,结果位才是1

主要就介绍这几个位运算符。

重点

枚举应用

一个NSUInteger类型,为什么能枚举出许多种类型?
1,2,4,8,16,32,64,128
我们设置推送类型属性赋值 NotificationType = 7,那我们如何判断这个推送类型包含那些枚举呢?
我们要看看这个属性包含哪些选项,这时候只需要将 NotificationType 和某个选项进行 & 操作即可判断出属性是否包含这一选项。

if (types&UNNotificationPresentationOptionBadge){
 //包含
}

types&UNNotificationPresentationOptionBadge相当于 00000111&00000001 的结果是00000001 = 1,if 判断为真,则types 包含 UNNotificationPresentationOptionBadge。

在我们的开发中,需要多个为枚举类型的属性匹配多个枚举项时,可以考虑上述方式。

多选列表应用

在我们的开发过程中,很多时候会遇到这种需求,一个支持单选和多选列表:
也可以利用位元算来实现
假如有默认项:
我们定义一个属性选中项 tokenType = 0默认值为0;在列表处理时可以通过以下代码来判断:

 NSInteger tempToken = 1 <<  indexPath.row;
    if (self.tokenType & tempToken) {
        //处理包含选项
    }else{
        //处理不包含选项
    }
    
    if (self.tokenType == 0  &&  indexPath.row == 0) {
        //处理默认选项
    }

在给列表项目赋值时,可以做以上操作。

在处理选择操作时可以通过以下代码处理:

NSInteger tempToken = 1 <<  indexPath.row;
    
    if (self.tokenType & tempToken) {
        self.tokenType = self.tokenType - tempToken;
    }else{
        self.tokenType = self.tokenType | tempToken; 
    }
    if (tempToken == 1) {
        self.tokenType =  0;
    }
    [tableView reloadData];//刷新列表

这样处理会让代码更加简洁,同时在处理结果的时候可以只处理一个 integer 就可以。

诸如此类,我们可以利用位运算处理很多开发中的问题。

上一篇下一篇

猜你喜欢

热点阅读