【轉】Cocoa中的位與位運算

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

介紹

位操做是程序設計中對位模式或二進制數的一元和二元操做. 在許多古老的微處理器上, 位運算比加減運算略快, 一般位運算比乘除法運算要快不少. 在現代架構中, 狀況並不是如此:位運算的運算速度一般與加法運算相同(仍然快於乘法運算).(摘自wikipedia)javascript

OC做爲c的擴展和超集,位運算天然使用的是c的操做符。c提供了6個位操做符,$,|,^,~,<<,>>。本文不打算作位運算的基礎教學,只介紹一些開發中能用到的場景。java

提升運算速度

如前一段所說,位運算的運算速度是一般與加法速度至關,可是快於乘法運算的。故而若是咱們的程序對性能有要求,咱們可使用位運算來提升運算速度。好比:git

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

基於乘除法的位運算提速還有不少,這裏不一一列舉。須要注意的是,你應當只在遇到性能瓶頸的時候,而且瓶頸的確是計算的時候才這麼作。由於使用位運算並不利於程序的可讀性和可維護性。(科學計算除外)github

壓縮空間

之前接觸過ACM的筒子們應該對狀態壓縮不陌生,狀態壓縮的目的在於把一個大數據用有限的內存空間來進行表示。好比 Programming Pearls 裏面的一個經典示例:如何對最多有一千萬條不重複的7位整數(電話號碼)進行排序?且可以使用的內存空間有大約1MB多。架構

顯而易見的常規作法既是作一個基於磁盤操做的外排序。然而若是轉換一下思路,充分的使用內存中的每個位,加上不存在重複的電話號碼,以及不存在0和1開頭的電話號碼。咱們只須要使用1000萬個位(大約1.2mb),就能以集合的方式在內存裏標記下全部的數據,從而輕鬆的實現位排序。此種方法大幅度的減小了IO時間,從而得到巨大的性能提高。app

ACM裏面有大量的若是使用位來壓縮空間的示例,狀態壓縮的動態規劃等,此處不作展開,只告訴讀者,充分的使用內存的每個位,常常能帶來意想不到的收穫。但須要注意的是,狀態的壓縮和提取,都須要必定的計算量,有時一味的追求狀態壓縮,反而會下降效率。ide

表示數據

比較經典的一個應用場景,使用一串24位的十六機制數字來表現一個RGB顏色(或者32位來表示ARGB)。因爲PS,Web以及各種取色器,都能快速的取出RGB的Hex值,可是UIColor沒有對應的方法。故而咱們能夠寫出下面這樣一個UIColor的Category,來快速的用一個RGBHex生成一個UIColor。(源碼在 UIColor + CYHelper.h )oop

+ (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

相關文章
相關標籤/搜索