转自:http://www.tuicool.com/articles/niEVjy

介绍

位操作是程序设计中对位模式或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加法运算相同(仍然快于乘法运算).(摘自wikipedia)

OC作为c的扩展和超集,位运算自然使用的是c的操作符。c提供了6个位操作符,$,|,^,~,<<,>>。本文不打算做位运算的基础教学,只介绍一些开发中能用到的场景。

提高运算速度

如前一段所说,位运算的运算速度是通常与加法速度相当,但是快于乘法运算的。故而如果我们的程序对性能有要求,我们可以使用位运算来提高运算速度。比如:

  • 乘以2:n << 1;
  • 除以2:n >> 1;
  • 乘以2的m次方:n << m;
  • 除以2的m次方:n >> m;
  • 判断奇偶:(n & 1) == 1;
  • 求平均数:(a + b) >> 1;
  • ……

基于乘除法的位运算提速还有很多,这里不一一列举。需要注意的是,你应当只在遇到性能瓶颈的时候,并且瓶颈的确是计算的时候才这么做。因为使用位运算并不利于程序的可读性和可维护性。(科学计算除外)

压缩空间

以前接触过ACM的筒子们应该对状态压缩不陌生,状态压缩的目的在于把一个大数据用有限的内存空间来进行表示。比如 Programming Pearls 里面的一个经典示例:如何对最多有一千万条不重复的7位整数(电话号码)进行排序?且可使用的内存空间有大约1MB多。

显而易见的常规做法既是做一个基于磁盘操作的外排序。然而如果转换一下思路,充分的使用内存中的每一个位,加上不存在重复的电话号码,以及不存在0和1开头的电话号码。我们只需要使用1000万个位(大约1.2mb),就能以集合的方式在内存里标记下所有的数据,从而轻松的实现位排序。此种方法大幅度的减少了IO时间,从而获得巨大的性能提升。

ACM里面有大量的如果使用位来压缩空间的示例,状态压缩的动态规划等,此处不做展开,只告诉读者,充分的使用内存的每一个位,经常能带来意想不到的收获。但需要注意的是,状态的压缩和提取,都需要一定的计算量,有时一味的追求状态压缩,反而会降低效率。

表示数据

比较经典的一个应用场景,使用一串24位的十六机制数字来表现一个RGB颜色(或者32位来表示ARGB)。由于PS,Web以及各类取色器,都能快速的取出RGB的Hex值,但是UIColor没有对应的方法。故而我们可以写出下面这样一个UIColor的Category,来快速的用一个RGBHex生成一个UIColor。(源码在 UIColor + CYHelper.h )

+ (UIColor *)colorWithRGBHex:(UInt32)hex
{
return [UIColor colorWithRGBHex:hex alpha:1.0f];
} + (UIColor *)colorWithRGBHex:(UInt32)hex alpha:(CGFloat)alpha
{
int r = (hex >> 16) & 0xFF;
int g = (hex >> 8) & 0xFF;
int b = (hex) & 0xFF; return [UIColor colorWithRed:r / 255.0f green:g / 255.0f blue:b / 255.0f alpha:alpha];
}

状态与选项

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
UIViewAnimationOptionLayoutSubviews = 1 << 0,
UIViewAnimationOptionAllowUserInteraction = 1 << 1, // turn on user interaction while animating
UIViewAnimationOptionBeginFromCurrentState = 1 << 2, // start all views from current value, not initial value
UIViewAnimationOptionRepeat = 1 << 3, // repeat animation indefinitely
UIViewAnimationOptionAutoreverse = 1 << 4, // if repeat, run animation back and forth
UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, // ignore nested duration
UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, // ignore nested curve
UIViewAnimationOptionAllowAnimatedContent = 1 << 7, // animate contents (applies to transitions only)
UIViewAnimationOptionShowHideTransitionViews = 1 << 8, // flip to/from hidden state instead of adding/removing
UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, // do not inherit any options or animation type UIViewAnimationOptionCurveEaseInOut = 0 << 16, // default
UIViewAnimationOptionCurveEaseIn = 1 << 16,
UIViewAnimationOptionCurveEaseOut = 2 << 16,
UIViewAnimationOptionCurveLinear = 3 << 16, UIViewAnimationOptionTransitionNone = 0 << 20, // default
UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20,
UIViewAnimationOptionTransitionFlipFromRight = 2 << 20,
UIViewAnimationOptionTransitionCurlUp = 3 << 20,
UIViewAnimationOptionTransitionCurlDown = 4 << 20,
UIViewAnimationOptionTransitionCrossDissolve = 5 << 20,
UIViewAnimationOptionTransitionFlipFromTop = 6 << 20,
UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20,
} NS_ENUM_AVAILABLE_IOS(4_0);

我们观察Apple在UIViewAnimationOptions的枚举变量,使用了一个NSUInteger就表示了UIViewAnimation所需的所有Option。其中0~9十个是互不影响的可同时存在option。16~19,20~24使用了4位来表示互斥的option。

如此定义了之后,对UIViewAnimationOptions的赋值变得尤为简单,使用 | 操作符既可以获得一个给对应的option位赋值后的结果。例如:

    [UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionAllowUserInteraction
| UIViewAnimationOptionBeginFromCurrentState
| UIViewAnimationOptionCurveEaseIn
animations:{...}
completion:{...}];

提取也比较简单,使用 & 操作符 和 >> 操作符,就可以轻松判定某个位有没有被设置,以及提取某些状态位,例如:

UIViewAnimationOptions option = UIViewAnimationOptionAllowUserInteraction
| UIViewAnimationOptionBeginFromCurrentState
| UIViewAnimationOptionCurveEaseIn
| UIViewAnimationOptionTransitionCrossDissolve; if (option & UIViewAnimationOptionAllowUserInteraction) {
NSLog(@"UIViewAnimationOptionAllowUserInteraction has been set");
}
if (option & UIViewAnimationOptionBeginFromCurrentState) {
NSLog(@"UIViewAnimationOptionBeginFromCurrentState has been set");
}
UInt8 optionCurve = option >> 16 & 0xf;
if (optionCurve == 1) {
NSLog(@"UIViewAnimationOptionCurveEaseIn has been set");
}
UInt8 optionTransition = option >> 20 & 0xf;
if (optionTransition == 5) {
NSLog(@"UIViewAnimationOptionTransitionCrossDissolve has been set");
}

这里最需要注意的地方就是,对互斥的状态的设置必须尤为小心,如果你这么写:

UIViewAnimationOptions badOption = UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionCurveEaseOut;
UInt8 oops = badOption >> 16 & 0xf;
NSLog(@"Sorry, it's not UIViewAnimationOptionCurveEaseInOut");
NSLog(@"oops = %d, you got UIViewAnimationOptionCurveLinear", oops);

联系我

  • 写邮件:lancy1014#gmail.com
  • 关注我的 微博
  • Fo我的 Github
  • 在这里写评论留言

Lancy

9.27

【转】Cocoa中的位与位运算的更多相关文章

  1. Python语言中的按位运算

    (转)位操作是程序设计中对位模式或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加 ...

  2. Integer中的奇妙位运算

    Integer中的奇妙位运算 参考资料 https://segmentfault.com/a/1190000015763941 highestOneBit(int i) 函数的作用是获得传入参数的最高 ...

  3. C++中巧妙的位运算

    位运算要多想到与预算和异或运算,并常常将两个数对应位上相同和不同分开处理 一.x&(x-1)消除x二进制中最右边的一个1. 这个比较厉害,比如统计某个 二.与和异或的巧妙结合的思想 与运算可以 ...

  4. 状态压缩中常用的位运算(DP)

    面对位运算,一直很无感...可能数学太差,脑洞太小. 1.首先是最基本的: 与&,或|,非~,异或^. 2.获取一个或者多个固定位的值: 假设 x = 1010(二进制),我们要取左数第二位的 ...

  5. Java中的按位运算

    博客大搬家. 一.位运算符简介: 1.按位与&.如果两个整形数据 a.b 对应位都是1,则结果位才为1,否则为0,(int 最大值0x7fffffff ): int a = 0x7ffffff ...

  6. C语言中的重要位运算

    1. 常用的等式 :-n = ~(n-1) = ~n + 1. 2. 获取整数n的人进制形式中的最后1个,也就是只保留最后一个1,其余的全部置位0,如1000 0011 --->  0000 0 ...

  7. 嵌入式C语言位运算之清位置位

    如题,在嵌入式开发中,掌握位运算是节省开发时间和提高开发效率的一种高效方式. 我们不得不去熟悉如何快速掌握位运算这种高效的技巧,接下来看看程序.. #include <stdio.h> # ...

  8. jave 逻辑运算 vs 位运算 + Python 逻辑运算 vs 位运算

    JAVA中&&和&.||和|(短路与和逻辑与.短路或和逻辑或)的区别 博客分类: 面试题目 Java.netBlog  转自 :http://blog.csdn.net/web ...

  9. JAVA程序开发按位运算的记录

    忘记在哪里看到一个面试题:把int a,b的值互换,不能使用临时变量.刚开始完全懵逼,脑子里面全是浆糊,不知道如何下手.查看答案后猛地一惊,心想居然还有这种操作,真是叹为观止,真的感觉自己的基础是如此 ...

随机推荐

  1. 前端笔试题目小结--获取输入参数用户名;查询URL字符串参数

    编写一个JavaScript函数getSuffix,用于获得输入参数的后缀名.如输入abc.txt,返回txt. str1 = "abc.txt"; function getSuf ...

  2. 生成getter()、setter()方法去掉变量前缀

    当定义的变量名有前缀但是不想在生成它的getter()和setter方法的时候让前缀出现,比如今天项目的部分代码: public class Crime { private UUID mId; //标 ...

  3. Android入门1:使用VideoView和MediController播放视频

    最近在搞Android,入门曲线还是挺陡峭的,主要还是自己对Java的理解不够深入.前后学习了几天,把最近学习到的一些知识点总结归纳一下,正所谓温故而知新. 目前想搞一个禁播视频站,主要内容都是一些大 ...

  4. javascript 倒计时跳转.

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. window下Slik SVN的安装配置

    我相信各位都应该对SVN不会陌生吧,我相信绝大多数人都使用过,但是并不是人人都自己配置过SVN服务器.下面就是我配置SVN服务器的步骤,以及在配置过程中碰见的一些问题,在此记录,希望对你有所帮助. 安 ...

  6. 响应式Asp.net MVC企业网站源码

    最近时间充裕,自己写了一个响应式MVC企业网站系统,用于回顾自己的MVC知识.网站源码后台和前台都采用响应式布局,可以适应不同的屏幕. 一.源码描述 响应式企业网站系统,前台和后台都采用了响应式布局, ...

  7. GCD 深入理解

    GCD 深入理解(一) 虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Object ...

  8. objc runtime 动态增加属性

    objective-c中,有类别可以在不修改源码的基础上增加方法:近排在看别人的开源代码时,发现还可以动态增加属性.而且是在运行时,太牛B了. 使用运行时库,必须要先引入 objc/runtime.h ...

  9. vi使用入门指南

    一.Unix编辑器概述 编辑器是使用计算机的重要工具之一,在各种操作系统中,编辑器都是必不可少的部件.Unix及其相似的ix操作系统系列中,为方便各种用户在各个不同的环境中使用,提供了一系列的ex编辑 ...

  10. Codeforces 13C Sequence

    http://codeforces.com/contest/13/problem/C 题目大意 给定一个含有N个数的序列,要求你对一些数减掉或者加上某个值,使得序列变为非递减的,问你加减的值的总和最少 ...