看到CSDN有網友提出能否用純位運算實作if語句
int x;
//...
if(0 != x)
{
x = 1;
}
詳見
http://topic.csdn.net/u/20110710/10/19ce7d9b-01b7-4082-bb3b-1f4216c7223b.html
當然這是一道沒什麼意義的題目.相信樓主隻是為了好玩.
乍看之下似乎沒什麼可能,畢竟判斷是很基本的要素.
然而程式裡沒什麼不可能,有同學就寫出了以下幾個方案:
方案一:
x |= x >> 16
x |= x >> 8
x |= x >> 4
x |= x >> 2
x |= x >> 1
x &= 1
方案二:
x = x == 0? 0:1
這裡方案二是不符合要求的,因為?号其實就是if判斷,隻是寫法不同而已
方案一有點暴力.
我當時随便想了下提出了
x=((1<<x)>>(x-1))>>1
并簡單測試了幾個數,但後來被發現在臨界點32位的時候是有問題的,不知道是否32的倍數都會有問題,沒去測試,
思考其原因可能是優化的結果,或者是帶進位移位造成的,因為按理論是不會有問題的.
不過做程式時一些臨界點是很重要的,也是一般測試程式必要的測試點.
後來有同學提出了
x = (~((uint)x-1) | (uint)x) >> 31
比較完美的解決了問題,
x=(((uint)1<<x)>>(x-1))>>1
這個思想是讓1在非0的時候不移動,在0的時候往右移1位,可惜受到進位的影響,在32倍數時出現問題.
此外還有同學提出了!!x的方案,
x=!!x
這個方案非常簡潔明了,負負得正,消除其他位的1,可惜的是這個方案核心還是使用了比較
彙編代碼為
cmp dword ptr [x],0
setne al
是以最後總結方案為
x = (~((uint)x-1) | (uint)x) >> 31
這個方案還可以有另一個形式
((-(unsigned int)x) | x )>> 31
不過這個确實很好玩的,有時侯寫程式就應該多想想其他的思路,說不定就會有妙招出來.
遇到問題,不妨換個角度去思考,也許就豁然開朗了.
人生也是如此,在遇到絕境時,不妨換條路走走.說不定就是另一番天地.