標籤:
轉自: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中的位與位元運算