2014年11月10日

[C++] Tips of Calculating Floor and Ceiling on Integer Types

C/C++ 寫了一段時間的人,應該或多或少會遇到一些簡便的偷懶寫法,例如不用暫存變數就交換兩個變數的值之類的,這類技巧雖然多半有著先天的限制條件,但是適用場合因為相當的廣泛,所以用的人其實不少。

這次要介紹的小技巧是在給定兩個型態是整數型態的變數 a & b,計算 $\left\lfloor\frac{a}{b}\right\rfloor$ 跟 $\left\lceil\frac{a}{b}\right\rceil$ 。
如果計算完的結果是正整數,在 C/C++ 要計算 $\left\lfloor\frac{a}{b}\right\rfloor$其實相當簡單,只要相除即可,因為一般來說處理整數型態的除法時的做法相當於無條件捨去 (不過這牽涉到編譯器內部的處理方式,甚至是硬體是如何實作整數除法這回事)。

要計算 $\left\lceil\frac{a}{b}\right\rceil$ 就需要多一點點的手腳:
$$\left\lceil\frac{a}{b}\right\rceil = \left\lfloor\frac{a + b - 1}{b}\right\rfloor$$
取 floor 的手法就直接運用上面說的整數除法即可,這樣即可避免冗長的程式碼以及型態轉換,不然一般來說要計算 floor 或 ceiling 是要先轉型成浮點數,計算完再轉回原本的變數型態的。

不過誠如紅色字體所寫的,這在使用上是有很大的但書要注意
1. 結果要是正整數,因為正整數無條件捨去的結果才會剛好是 floor 的結果
2. 即便符合條件一,也不能保證這作法永遠可行。因為這並非 C/C++ 標準所規定的結果,乃是現在電腦常見作法下所導致的結果,換言之就算沒有換電腦,換編譯器都有可能導致結果不如預期。

不過反正現在電腦平臺差不多都被壟斷了,所以出問題的機率其實還真的不大,要是哪天真的非常幸運的遇上這種問題了,就去簽個樂透算了 XD

P.S. 
不用佔存變數就交換兩個變數值的做法是利用 bitwise operation:a ^= b ^= a ^= b
看到這種寫法應該就會知道使用上僅限於整數型態,而且最好是 unsigned 修飾過的型別

沒有留言:

張貼留言