C++負數取模


預習:

r=余數

a=被除數

b=除數

c=商

a/b=c........r

r=a-(a/b)*b

 

一、下面的題目你能全做對嗎?
1.7/4=?
2.7/(-4)=?
3.7%4=?
4.7%(-4)=?
5.(-7)/4=?
6.(-7)%4=?
7.(-7)/(unsigned)4=?
答案:
1
-1
3
3
-1
-3
1073741822
如過你全部答對,你可以無視后面的內容……

 

 

 

 

 

二、除法的取整分類
除法的取整分為三類:向上取整、向下取整、向零取整。
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的原因。
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的值由編譯器選取。需要注意的是,本公式只是除法優化中的一個典型代表,編譯器會根據除數對公式進行調整,但基本形式與原理是類似的。

轉載地址:http://tieba.baidu.com/p/1881961036

 

 

 

——————————————————————————————————————————

以下摘錄自C++ Primer(P130)

操作符%稱為“求余”或“求模”操作符,該操作符的操作數只能為整型。

如果兩個操作數為正,結果也為正;如果兩個操作數都為負數,結果也為負數;如果一個操作數為正數,一個操作數為負數,求模結果的符號取決於機器。

當操作數中有一個為負,一個為正是,求模操作結果值的符號可依據分子(被除數)或分母(除數)的符號而定。如果求模的結果隨分子的符號,則除出來的值向零一側取整;如果求模與分母的符號匹配,則除出來的值向負無窮大一側取整。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM