位操作與空間壓縮

2022-07-29 11:39:10 字數 2088 閱讀 2988

篩素數法在這裡不就詳細介紹了,本文著重對篩素數法所使用的素數表進行優化來減小其空間占用。要壓縮素數表的空間占用,可以使用位操作。下面是用篩素數法計算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

int j = 0

; j |= 1

<< 10

; printf(

"%d\n

", j);

同樣,可以1向左移位後與原數相與來判斷指定位上是0還是1(也可以將原數右移若干位再與1相與)。

//

判斷指定位上是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次...