接著上午有關 x&(x-1) 的另乙個例題:
用乙個表示式,判斷乙個數x是否是2n次方(2,4,8,16,…),不可用迴圈語句。
[中國台灣某著名cpu生產公司2023年10月面試題]
解析:2、4、8、16這樣的數轉化成二進位制是10、100、1000、10000。如果x減1後與x 做與運算,答案若是0,則x是2n次方。
答案:!(x&(x-1))
下午:1.
基本的優先順序需要記住:
指標最優,單目運算優於雙目運算。如正負號。
先算術運算,後移位運算,最後位運算。
邏輯運算最後計算。
請特別注意:1 << 3 + 2 && 7等價於 (1 << (3 + 2))&&7.
例:
一是型別轉換問題;二是算符的優先順序問題。
對於第乙個問題:
unsigned char b=~a>>4,在計算這個表示式的時候,
編譯器會先把a和4的值轉換為int型別(即所謂整數提公升)後再進行計算,
當計算結果出來後,再把結果轉換成unsigned char賦值給b。
對於第二個問題:
因為「~」的優先順序高於「>>」和「+」,本題的過程是這樣的:
先對於1010 0101取反0101 1010;再右移
這裡有乙個問題,是先右移4位再加1呢,還是直接右移5(4+1)位。
因為「+」的優先順序高於「>>」,所以直接右移5位。結果是0000 0010。
最後的結果應該是2才對,但把如上的指令放到vs2008中執行,答案居然是250。
那麼到底是什麼地方出了問題?在除錯的過程中進入彙編指令。可以看到高階語句轉換為組合語言以後,是先執行取反再位移的。
我們看到eax是16位的暫存器,於是在機器中
0xa5的寄存中表達是0000 0000 1010 0101 ,
取反是1111 1111 0101 1010,
那麼右移5位是0000 0111 1111 1010,
由於是unsigned char型的只能表示低8位的數值,即250
(x&y)+((x^y)>>1),效果就是求x與y的平均值
把x和y裡對應的每一位(指二進位制位)都分成三類,每一類分別計算平均值,最後彙總。
其中 一類是x,y中對應位 都是1, 用x&y計算其平均值;
一類是x,y中對應位 有且只有一位是1,用(x^y)>>1計算其平均值;
一類是x,y中對應位 均為0, 無須計算。
第一部分:
x,y對應位均為1,相加後再除以2還是原來的數,如兩個00001111相加後除以2仍得00001111。
第二部分:
對應位有且只有一位為1,用「異或」運算提取出來,然後》1(右移一位,相當於除以2)。
第三部分:
對應位均為零,因為相加後再除以二還是0,所以不用計算。
三部分彙總之後就是(x&y)+((x^y)>>1)
這樣可以避免溢位:
假設x,y均為unsigned char型資料(0~255,占用一位元組),顯然,x,y的平均數也在0~255之間,但如果直接x+y可能會使結果大於255,這就產生溢位,雖然最終結果在255之內,但過程中需要額外處理溢位的那一位,在彙編中就需要考慮這種高位溢位的情況,如果(x&y)+((x^y)>>1)計算則不會。
3.利用 位運算 實現兩個整數的 加法運算
!!!!!!重點: 異或 常被認作不進製的加法運算
#include
int main(void)
int add(int a,int b)
注釋:* x ^ y :實現不進製的加法,那麼我們接下來就要將進製的資料加上,就可以實現了。
* x & y : 這個操作,即是找出相同位,為什麼我們需要找出相同的位呢,因為只 1 & 1 ,這種情況才會 產生進製,可能有人會想那 0 & 0 呢,這個沒有影響的。
* (x & y) << 1:為什麼要左移呢,其實也很簡單,即然後我們都已經找出需要進製的位,那麼說明在該位置的前面一位,應該加上1,所以應該左移1位,就是加上餘數4.
有兩個變數a和b,不用「if」、「?:」、「switch」或其他判斷語句,找出兩個數中間比較大的。
第一種:
int max = ((a+b)+abs(a-b))/2;
abs是取絕對值。
如果a>b,那麼a-b>0,所以表示式就變成了(a+b+a-b)/2=(a+a)/2=a。
如果a第二種:
int c = a-b;
char *strs[2] = ;
c = unsigned(c)>>(sizeof(int)*8-1);//判斷符號位
注釋:sizeof(int) 位元組數
sizeof(int)*8 位數
右移sizeof(int)*8 - 1 符號位
該語句的目的是求出c的最高位的值,
當該值為1時,表示c為負數,因此判斷出a小於b。
當該值為0時,表示c為零或者整數,因此判斷出a大於等於b
5.給三個整數a、b、c,函式實現取三個數的中間數,不可以使用sort,整數操作盡可能少。
(思路:輸入的三個值 中值就是第二大的數值
選中兩個進行比較 找到較大的
較大的與第三個值比較
1.如果較大的 < 第三個值 那這個較大的 就是第二大的數值 就是中值
2.較大的 > 第三個值 比較第三個值與 較小的值
1.第三個值 > 較小的值 第三個值 是中值
2.第三個值 < 較小的值 較小的值 是中值)
注意等於號
int median( int a, int b, int c )
else
// 此時有 min<=max
if ( max <= c )
return max;
else // min <= max, c }6.
如何將a、b的值進行交換,並且不使用任何中間變數?
(單純的加減交換會有溢位的可能 盡量用異或)
void swap(int& a, int& b) //使用位運算也可以交換兩個值
7.評價一下c與c++的各自特點。如果乙個程式既需要大量運算,又要有乙個好的使用者介面,還需要與其他軟體大量交流,應該怎樣選擇合適的語言?
因為c++是物件導向的,在封裝、繼承、多型這些特性上,會有比較大的開銷,所以單從執行效率而言,c更適合一些。
但是和c++相比,c的圖形庫相對而言種模擬較少,而且比較簡單,所以在比較複雜的介面設計上,c++會更有優勢。因此到底用c還是c++並沒有並且的答案,如果目標平台的硬體效能比較弱,並且gui介面比較簡單,推薦用c,反之推薦c++。
套題8 22 下午
count 問題描述 李華終於逃離了無盡的英語作文,重獲自由的他對一棵樹產生了興趣。首先,他想知道一棵樹是否能分成大小相同的幾塊 即切掉一些邊,使得每個 連通塊的點數相同 然後,他覺得這個問題過於簡單,於是他想知道一共有多 少種方案可以把這棵樹分成大小相同的幾塊。然後他發現自己不會了,於是向聰明的你...
濟南刷題衝刺 Day1 下午
time limit 1000ms memory limit 128mb 題目描述 lyk出了道水題。這個水題是這樣的 有兩副牌,每副牌都有n張。對於第一副牌的每張牌長和寬分別是xi和yi。對於第二副牌的每張牌長和寬分別是aj和bj。第一副牌的第i張牌能覆蓋第二副牌的第j張牌當且僅當xi aj並且y...
7 19晚牛客網刷題未知點 錯題 集合
初始化為null 0 的類指標可以安全的呼叫不涉及類成員變數的類成員函式而不出錯,但是如果類成員函式中呼叫了類成員變數則會出錯 2.悄咪咪加乙個注意點 注意enum在c語言中是關鍵字 c語言對大小寫比較敏感,所以enum是乙個識別符號,但不是關鍵字。3.include usingnamespace ...