C C 除法實現方式及負數取模詳解

2021-08-08 15:44:30 字數 2219 閱讀 6198

一、下面的題目你能全做對嗎?

1.7/4=?

2.7/(-4)=?

3.7%4=?

4.7%(-4)=?

5.(-7)/4=?

6.(-7)%4=?

7.(-7)/(unsigned)4=?

答案:1-13

3-1-31073741822

如過你全部答對,你可以無視後面的內容……

二、除法的取整分類

除法的取整分為三類:向上取整、向下取整、向零取整。

1.向上取整:向+∞方向取最接近精確值的整數。在這種取整方式下,7/4=2,7/(-4)=-1,6/3=2,6/(-3)=-2

2.向下取整:向-∞方向取最接近精確值的整數。在這種取整方式下,7/4=1,7/(-4)=-2,6/3=2,6/(-3)=-2

3.向零取整:向0方向取最接近精確值的整數,換言之就是捨去小數部分,因此又稱截斷取整。在這種取整方式下,7/4=1,7/(-4)=-1,6/3=2,6/(-3)=-2

通過觀察可以發現,無論是向上取整還是向下取整,(-a)/b==-(a/b)都不一定成立。這給程式設計者帶來了極大的麻煩。而對於向零取整,(-a)/b==-(a/b)是成立的,以此,c/c++採用這種取整方式。

三、負數取模

回想小學的公式:被除數÷除數=商……餘數。

由此可知,餘數=被除數-商×除數 (*)

對c/c++而言,(*)式依然成立。並且,該式是解決負數取模問題的關鍵。

例一:7%(-4)=?

解:由c/c++向零取整的整除方式可知,7/(-4)=-1;由(*)式知,餘數=7-(-4)*(-1)=3.所以,7%(-4)=3

例二:(-7)%4=?

解:由c/c++向零取整的整除方式可知,(-7)/4=-1;由(*)式知,餘數=(-7)-4*(-1)=-3.所以,(-7)%4=-3

例三:(-7)%(-4)=?

解:由c/c++向零取整的整除方式可知,(-7)/(-4)=1;由(*)式知,餘數=(-7)-(-4)*1=-3.所以,(-7)%(-4)=-3

四、相關知識的拓展

1.對於有符號整數與無符號整數間的除法,c/c++會將有符號整數轉換為無符號整數,需要特別注意的是,符號位並沒有丟失,而是變成了資料位參與運算。這就是(-7)/(unsigned)4不等於-1,而等於1073741822的原因。

此處原創:

這裡為啥呢。兩個不同符號位的數進行運算,需要轉換成同乙個符號位的數,有個規則,如果無符號的數大於等於有符號的數,那麼將有符號位的數轉換成無符號的,如果無符號的數小於有符號的數,那就要看編譯器了。假設int是32位,那麼可以表示的最大就是4294967296,這時候,用-7對這個數取模,得到4294967289,這就是轉換後得到的無符號位的數,然後再用這個數除4,就是1073741822,餘數是1

2.編譯器對除法的優化

①在「無優化」條件下,編譯器會在不影響正常除錯的前提下,對除法進行簡單的優化。

a.「常量/常量」型除法:編譯器會直接計算出結果。

b.「變

量/變數」型除法:無優化。

c.「變數/常量」型除法:若常量≠2^n,無優化;否則,除法將被轉換為右移運算。由於由右移運算實現的整除實質上是向下取整,所以編譯器會通過一些附加的指令在不產生分支結構的情況下將向下取整轉換為向零取整。

以【變數/2^3】為例,反彙編**如下:

mov eax,被除數

cdq ;若eax<0,則edx=0xffffffff;否則edx=0

and edx,7 ;若eax<0,則edx=7;否則edx=0

add eax,edx ;若eax<0,【(eax+7)/(2^3)】向下取整的值 與 【eax/(2^3)】向零取整的值相等,從而實現向零取整

sar eax,3 ;右移,完成除法

②在「o2優化」條件下,「變數/常量」型除法中,常量若≠2^n,也可以優化。此時,除法將被轉換為乘法與右移的結合形式。例如,a/b=a*(1/b)=a*((2^n)/b)*(1/(2^n)),其中,((2^n)/b為magicnumber,由編譯器在編譯過程中算出。這樣a/b就變成了(a*magicnumber)>>n,n的值由編譯器選取。需要注意的是,本公式只是除法優化中的乙個典型代表,編譯器會根據除數對公式進行調整,但基本形式與原理是類似的。

4 3 1原碼除法及實現

目錄 4.3.1原碼除法及實現 1.原碼除法演算法 原碼恢復餘數演算法 原碼不恢復餘數演算法 加減交替演算法 涉及減法操作 移位操作 邏輯移位 大致過程 第一次上商判溢位。用部分餘數減去被除數絕對值 通過加上被除數絕對值的相反數的補碼來實現 如果結果大於0,則上商1,部分餘數左移一位。如果結果小於0...

C C 中移位實現乘除法運算

用移位實現乘除法運算 a a 4 b b 4 可以改為 a a 2 b b 2 說明 除2 右移1位 乘2 左移1位 除4 右移2位 乘4 左移2位 除8 右移3位 乘8 左移3位 通常如果需要乘以或除以2的n次方,都可以用移位的方法代替。大部分的c編譯器,用移位的方法得到 比呼叫乘除法子程式生成的...

資料鑽取的場景及實現方式

資料鑽取是商業智慧型 bi 的概念,資料鑽取是按照某個特定層次結構或條件進行資料細分呈現,讓使用者關注的資料範圍從乙個比較大的面,逐步下鑽並聚焦到乙個小的點上 在wyn enterprise中,鑽取的應用場景主要包含以下幾個方面 1.報表與報表之間的資料鑽取 2.儀表板到報表的資料鑽取 3.儀表板智...