篩素數法在這裡不就詳細介紹了,本文著重對篩素數法所使用的素數表進行優化來減小其空間占用。要壓縮素數表的空間占用,可以使用位操作。下面是用篩素數法計算100以內的素數示例**(注2):
#include #include執行結果如下:const
int maxn = 100
;bool
flag[maxn];
int primes[maxn / 3 + 1
], pi;
//對每個素數,它的倍數必定不是素數。
//有很多重複如flag[10]會在訪問flag[2]和flag[5]時各訪問一次
void
getprime_1()
}void
printfarray()
intmain()
在上面程式是用bool陣列來作標記的,bool型資料佔1個位元組(8位),因此用位操作來壓縮下空間占用將會使空間的占用減少八分之七。
下面考慮下如何在陣列中對指定位置置1,先考慮如何對乙個整數在指定位置上置1。對於乙個整數可以通過將1向左移位後與其相或來達到在指定位上置1的效果,**如下所示:
//同樣,可以1向左移位後與原數相與來判斷指定位上是0還是1(也可以將原數右移若干位再與1相與)。在乙個數指定位上置1
int j = 0
; j |= 1
<< 10
; printf(
"%d\n
", j);
//擴充套件到陣列上,我們可以採用這種方法,因為陣列在記憶體上也是連續分配的一段空間,完全可以「認為」是乙個很長的整數。先寫乙份測試**,看看如何在陣列中使用位操作:判斷指定位上是0還是1
int j = 1
<< 10
;
if ((j & (1
<< 10)) != 0
) printf(
"指定位上為1");
else
printf(
"指定位上為0
");
#include int執行結果如下:main()
;
inti;
//在第i個位置上寫1
for (i = 0; i < 40; i += 3
) b[i / 32] |= (1
<< (i % 32
));
//輸出整個bitset
for (i = 0; i < 40; i++)
putchar('\n
');return0;
}
可以看出該陣列每3個就置成了1,證明我們上面對陣列進行位操作的方法是正確的。因此可以將上面篩素數方法改成使用位操作壓縮後的篩素數方法:
#include #include同樣執行結果為:const
int maxn = 100
;int flag[maxn / 32 + 1
];int primes[maxn / 3 + 1
], pi;
void
getprime_1()
}void
printfarray()
intmain()
另外,還可以使用c++ stl中的bitset類來作素數表。篩素數方法在筆試面試出現的機率還是比較大的,能寫出用位操作壓縮後的篩素數方法無疑將會使你的**脫穎而出,因此強烈建議讀者自己親自動手實現一遍,平時多努力,考試才不慌。
位操作的壓縮空間技巧也被用於strtok函式的實現,請參考《strtok原始碼剖析 位操作與空間壓縮》(
注2.這種篩素數的方法很樸素,會多次重複訪問資料,有什麼辦法能改進一下嗎?請看《改進的篩素數方法》一文
臨時表空間的查詢與壓縮
查詢臨時表空間 select f.tablespace name,d.file name tempfile name round f.bytes free f.bytes used 1024 1024,2 total mb round f.bytes free f.bytes used nvl p....
位 位元組 進製梳理與位操作
位 bit 是計算機最基礎也是最小的資料度量 位是二進位制數例如 10101010 每乙個數字便是一位 bit 位元組 每一位元組有8位8bit 進製是進製,位是位 16進製制數0xffffffff 其中0x是16進製制數的標誌,表示標誌後面的數是16進製制的 其中每乙個f可以表示成二進位制數 11...
許可權操作與位運算
php 我這裡說到的許可權管理辦法是乙個普遍採用的方法,主要是使用到 位執行符 操作,位與運算子 位或執行符。參與運算的如果是10進製數,則會被轉換至2進製數參與運算,然後計算結果會再轉換為10進製數輸出。它的許可權值是這樣的 2 0 1,相應2進數為 0001 在這裡 我表示成 次方 即 2的0次...