x y x y 1 作用及其優點

2021-09-27 03:26:27 字數 2798 閱讀 3809

(x&y) + ((x^y)>>1)作用及其優點

作用

《程式設計師面試寶典》第四版39頁的題:

int func(int x, int y)

func(729,271)是多少?思路最簡單也最直接的就是將x和y都先轉換為二進位制,然後老老實實的做按位與,按位異或等運算,最後得出結果。

首先說明該表示式的作用就是求兩數的平均值,也就是說func(729,271)= (729+271)/2=500。下面說明該表示式的思路。對於二進位制的位運算(&、|、^、~),某位的運算無非就是三種情況:(1)1與1運算;(2)1與0運算;(3)0與0運算。

1與0運算:1&0結果為0,1^0結果為1,那麼只考慮^運算,該位就是1。而0^1可看成(0+1) =1。

1與1運算:兩個數的二進位制運算中若某位上兩個數均為1,則1&1為1,1^1的結果為0,那麼只考慮&運算。而1&1可看成(01+01)>>1 =01(考慮進製)。當然可以看成是(1+1)/2=1,但是這時的1是十進位制,不是二進位制。

0與0運算:0&0為0,0^0為0,則均不用考慮,該位為0即可。

由上面分析可得,對(x & y)與((x ^ y) >> 1)的計算,可以把x和y對應的二進位制每一位拆開來分別計算,那麼可分成三類,每一類分別計算,最後相加。其中,一類是x,y對應位都是1,用x&y計算;一類是x,y中對應位有且只有一位是1,用(x^y)>>1計算;還有一另是x,y中對應位均為0,無須計算,因此這一類可以忽略,也就是說實際只需考慮前兩類即可。

舉例子來說:5和13對應的二進位制分別為0101和1101,把對應的二進位制數拆開來看:5=0000+0100+0000+0001,13=1000+0100+0000+0001,那麼

5&13=

0000 +

0100

+0000 +

0001&

&& &

1000

0100

0000

0001

5^13=

0000

+0100 +

0000 +

0001 ^

^ ^

^ 1000

0100

0000

0001 所以

(5&13)+ (5^13)>>1=

0100

+0001

+0000

>>1

&&^

0100

0001

1000

即((5^13)>>1)+ (5&13) =((0000 ^ 1000)>>1)  +  (0100 & 0100  +  0001 & 0001)

由以上分析可得:

(5^13)>>1 = (0000 ^ 1000)>>1

=(0000 + 1000)>>1

5&13 = 0100 & 0100  +  0001 & 0001

=(0100 + 0100)>>1  +  (0001 + 0001)>>1

所以((5^13)>>1)8 + (5&13) =((0000 ^ 1000)>>1)  +  (0100 & 0100  +  0001 & 0001)

=(0000 + 1000)>>1  + (0100 + 0100)>>1  +  (0001 + 0001)>>1

=((0000 + 1000) + (0100 + 0100) + (0001 + 0001))>>1

而5+13=

0000

+0100

+0000 +

0001++

& +1000

0100

0000

0001

即5+13 =(0000 + 1000)  +  (0100 + 0100)  +  (0001 + 0001)。已知乙個十進位制數除以2相當於其對應的二進位制向右移一位,所以有:

(5+13)/2 =/2

=((0000 + 1000)  +  (0100 + 0100)  +  (0001 + 0001))>>1

= (5^13)>>1  +  (5&13)

因此(5+13)/2 = (5&13) + (5^13)>>1  (表示將裡面的二進位制轉換成十進位制數)

綜上可得,求平均數的過程是先用與運算對數值做部分平均值的提取,然後用異或並右移運算獲得餘下部分的平均值,因此這兩部分的平均值相加後就得出了原來兩數的平均值。實際上,這是乙個加法分解然後綜合的過程。如上面的5和13,先做與運算,也就相當於從5和13 裡分別先減去5,剩下0和8,再將這兩數相加得8(異或運算),然後再除以2(右移),結果為4。最後5+4等於9,即得最後所要的結果。

儘管上面的過程看來上去實際用處不是很大,但如果是用在沒有乘除法指令的簡單微控制器系統,移位和邏輯運算操作就顯得很重要了。

優點

由上可知原函式返回值就是(x+y)/2,因此可改寫為:return (x+y)/2。但實際上,這樣的改寫雖然使得函式的功能清晰了然,但是這樣的改寫並不好,因為對於兩個int型別的整數x,y,如果用(x+y)/2求他們平均值,完全有可能會產生溢位。因為x+y可能會大於int_max,但是我們知道它們的平均值是肯定不會溢位的。所以使用

(x & y) + ((x ^ y) >> 1)

來計算平均值的好處就是可以避免溢位,因為位運算不涉及加法,所以肯定不會產生溢位。

關於 x y x y 1 的解析

原題 int f int x,int y f 729,271 x y x y 1 書上解析說這個函式的功能是取兩個數的平均數。不太明白,查了資料加上整理一下,僅作記錄。一種解釋是 把x和y裡對應的每一位 指二進位制位 都分成三類,每一類分別計算平均值,最後彙總。其中,一類是x,y對應位都是1,用x ...

x y x y 1 求平均值

x y x y 1 把x和y裡對應的每一位 指二進位制位 都分成 三部分,每一部分 分別計算平均值,最後彙總 其中,第一部分 是x,y對應位都是1,用x y計算其平均值 第二部分 是x,y中對應位有且只有一位是1,用 x y 1計算其平均值 第二部分 是x,y中對應位均為0,無須計算。下圖詳細說明 ...

求平均數 x y x y 1 原理

x y x y 1 能求x與y的平均數,其原理1如下 設兩數如下 x y取出同為1的位,如下 00110 由此數一定小於等於原來如何乙個數,由此數加乙個數可以得到原來數,由此將原來的兩數相加變成4數相加,如下 相當於 00110乘以2 x y乘以2 而後兩數相加就是x y,相當於 x y乘以2 x ...