![](/img/trans.png)
[英]BitSet(JAVA) is throwing outofBoundsException in the implementation of Sieve Of Eratosthenes
[英]Translating this java implementation of Sieve of Eratosthenes?
這是Java中的程序,通過將布爾數組存儲為位數組來實現Sieve或Eratosthenes。 我以前從未用Java編寫過代碼,但是總體思路很容易理解。 但是,我不明白getBit
和setBit
函數如何工作? 我猜想getBit
函數會創建一個我將其設置為1的位掩碼,並且在掩碼和數組之間按位AND
嗎? 但是,我並不是很了解細節(例如,為什么我在作為索引傳遞給數組之前右移4,以及為什么MEMORY_SIZE
等於右移4的MAX
)。 請用語言解釋getBit
和setBit
的每個步驟,如果可能的話,請在Python中等效的實現?
private static final long MAX = 1000000000L;
private static final long SQRT_MAX = (long) Math.sqrt(MAX) + 1;
private static final int MEMORY_SIZE = (int) (MAX >> 4);
private static byte[] array = new byte[MEMORY_SIZE];
//--//
for (long i = 3; i < SQRT_MAX; i += 2) {
if (!getBit(i)) {
long j = (i * i);
while (j < MAX) {
setBit(j);
j += (2 * i);
}
}
}
//--//
public static boolean getBit(long i) {
byte block = array[(int) (i >> 4)];
byte mask = (byte) (1 << ((i >> 1) & 7));
return ((block & mask) != 0);
}
public static void setBit(long i) {
int index = (int) (i >> 4);
byte block = array[index];
byte mask = (byte) (1 << ((i >> 1) & 7));
array[index] = (byte) (block | mask);
}
提前注意事項:
(i >> 4)
將i
除以16,這是包含第i
位的array
中(8位)塊的索引 (i >> 1)
將i
除以2 7
是111
((i >> 1) & 7)
表示“ i / 2
最右邊三個位”,它是介於0和7之間(包括0和7)的數字 (1 << ((i >> 1) & 7))
是0至7倍比特向左移位( 00000001
, 00000010
,..., 10000000
)。 這是位掩碼,用於設置/從所選塊中獲取感興趣的位。 getBit(i)
解釋
byte
)。 1
,則返回true
。 setBit(i)
解釋
getBit
編輯
第一個問題:
現在幾乎可以理解,您能否解釋一下為什么我們能夠通過向左移((i >> 1)&7)次來找到與數字i對應的位的位置? 換句話說,我理解該操作在做什么,但是為什么這會給我們正確的位位置呢?
我認為這是由於算法的優化性質。 因為i
以2的步長遞增,所以使用一半的位就足夠了(因為其他位還是會被設置)。 因此, i
可以被2除以計算必要的位移位數。
關於第二個問題:
另外,為了澄清起見,在每次調用setBit之后將j增加2 * i的原因是因為我們只需要設置與i的奇數倍對應的位,對嗎?
是的,因為根據https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes :
另一種改進是最初僅列出奇數(3、5,...,n),並在步驟3中以2p的增量計數,因此僅標記p的奇數倍。
您的算法以3開頭, i
遞增2,並以2*i
遞增。
我希望這有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.