技巧 求能被size整除的大於或等於num的最小值

2021-04-25 14:20:34 字數 1235 閱讀 6074

最近看到csdn上的一篇博文,提到了從驅動**裡發現的乙個奇怪巨集,如下:

#define e1000_roundup(num, size) ((num) = (((num) + (size) - 1) & ~((size) - 1)))

那篇文章的作者通過執行**認為此**的作用是求能被size整除的大於或等於num的最小值(size要為偶數),並且沒有給出解釋。

實際上,這段**的作用確實是求能被size整除的大於或等於num的最小值。但size的條件要示比較高,要為2的冪才可以。

我們可以試想這個巨集是怎麼想出來的。設size是2的n次冪,num共有m+n個二進位制位。要求能被size整除的大於或等於num的最小值,可以分為2部分來考慮:整除和進製。

首先是進製。如果num沒有恰好被size整除的話,肯定要在後n位加上待定的值來使前m位進1。暫且不考慮後n位,只要讓前m位加1,即加上2的n次方即可達到目的。但是如果num正好能被size整除,就不能進製了。因此可以加上2的n次方減1(即size-1)。

再次是整除,要被size整除,也就是要把num的後n位清零,同時保證前m位不變(因為進製的要求已經達到了)。c語言位操作中的「與」操作常用來完成 位清零和位保持的工作。只要將num與後n位為0的數作與操作即可將後n位清0。其餘的二進位制位與1作與操作即可保持相應位的值不變。因此,我們只要構造 乙個後n 位為0,其餘各位為1的數即可。由於1的位數要根據num值的大小來確定,因此這個數不好構造。但後n位為1,其餘各位為0的數很好構造,就是size- 1。只要將size-1的各位按位取反就可得到我們想要的數。因此整除的操作可以通過「&~(size-1)」來完成。

綜合起來,就是num=(num+size-1)&~(size-1)。將它變成巨集的時候要注意將各引數都用括號括起來,防止巨集展開的時候出現錯誤。因此就有了開篇的那句**:

#define e1000_roundup(num, size) ((num) = (((num) + (size) - 1) & ~((size) - 1)))

num=(num%size==0)?num:(num+size-num%size);

或者num=(num%size==0)?num:(num/size+1)*size;

很多時候我們都要求能被size整除的大於或等於num的最小值。比如linux下的des加密函式,要求只能對8位元組的整數倍的資料進行加密,如果不 是,就要在資料的後面補零變成8位元組的倍數再進行加密。8正好是2的冪,補0後的位元組數就可以用上面的巨集來求。同樣,將一段資料寫到作業系統的分頁 (4096位元組)裡也可以用上述的巨集。

不能被3整除的整數的和大於(或等於)2000的數字

這個題目真把我弄懵逼了。看了好久都沒看懂到底是什麼意思。求助了度娘才恍然大悟。特此記錄且查且珍惜。使用break控制程式 功能描述 計算出1 100之間所有不能被3整除的整數的和大於 或等於 2000的數字 int sum 0 不能被3整除的整數的和 int num 0 和大於等於2000的數 fo...

hdu 求n!是否能被m整除

個人覺得這是一道好題,用到了乙個我我熟悉的知識點。題目鏈結 首先求出m的所有質因子 p1,p2.pk 及其個數 s1s,s2.sk 然後再求n階乘中的因子 p1,p2.pk 個數是否大於 s1,s2.sk 問題的關鍵在於如何求n!中的質因子pi的個數,請看下面 int sum 0 while n p...

C 陣列連線求能被7整除的數

2018美團點評程式設計題2 思路 若乙個整數的個位數字截去,再從餘下的數中,減去個位數的2倍,如果差是7的倍數,則原數能被7整除。如果差太大或心算不易看出是否7的倍數,就需要繼續上述 截尾 倍大 相減 驗差 的過程,直到能清楚判斷為止。例如,判斷133是否7的倍數的過程如下 13 3 2 7,所以...