C語言中負數除法與右移取整問題

今天碰到了負數除法與右移的替代問題,藉機研究一下C語言中負數除法的問題。此處只討論整數除2的冪次方的情況,並取-7~-5除以4爲例,不討論一般除法的移位優化。

1.     負數右移

對於有符號整數,右移時按高位補符號位的原則,則結果會向小於它的整數取整。如

-5 >> 2 = -2;

-6 >> 2 = -2;

-7 >> 2 = -2;

2.     負數除法(截斷)

博文《議“右移一位 等同於 除以二”》http://blog.chinaunix.net/uid-406135-id-3421605.html中有這樣一段描述:C99C++0x規定,商向零靠近取整,在 C99 C++0x 之前,只保證*除數+餘數==被除數,如果希望商向零靠近取整,應當使用div函數。”

那上述算式就會有結果:

-5 / 4 = -1;

-6 / 4 = -1;

-7 / 4 = -1;

 

3.     負數除法(四捨五入)

四捨五入的意義就在於向臨近的整數取整,但問題就在於對.5這個臨界點如何進行處理。這裏有一種說法,即是說對於負數相除四捨五入的情況,可以先將符號拿掉,按正整數做除法,最後再把符號位加到結果上即可。那上述算式的結果應該爲:

-5 / 4 = -1;

-6 / 4 = -2;

-7 / 4 = -2;

sign(val) * (abs(val) +(1<< (n-1) )>> n)。

Microsoft Excel的取整就是採用這種方法。

 

但是,在ARM的NEON運算裏的rounding,以及java的Math.round()函數的返回值來看(參考http://www.cnblogs.com/jiutianhe/archive/2012/10/07/2755655.html):

在.5這個臨界點上,對於正負值都是向上取整。即是說按公式(val+ (1 << (n-1))) >> n進行計算。即:

-5 / 4 = -1;

-6 / 4 = -1;

-7 / 4 = -2;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章