0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

エラトステネスの篩(ふるい)を行う際の配列サイズについて

Last updated at Posted at 2023-09-19

はじめに

下記の自分の記事で配列サイズの見積もりを誤っていた。

JavaScript の場合わりと配列サイズはアバウトでよく,そもそもサイズも型も不定で var a = []; と宣言できてしまうし,var a = new Array(256); のようにサイズを定義して宣言した場合でも,当初宣言したサイズを超えたアクセス,たとえば a[300] に書き込んでも読み込んでもエラーにはならない。ただし,このようなアクセスを行うとパフォーマンスは格段に落ちることが知られている。詳しくは下記の記事を参照されたい。

最大のパフォーマンスを得るには必要な配列のサイズを最初に定義し,この範囲内でアクセスが完結するよう注意しなくてはならない。

自然数をそのまま配列に割り当てる場合

与えられた自然数 $N$ に対して,$N$ の平方根を超えない自然数最大値 $N_1 = [\sqrt{N}]$ までの素数を求める。素数判定を行う自然数 $i$ とすると範囲は $1 \le i \le N_1$ となる。この自然数 $i$ が素数か否かを判定する配列をそのまま a[i] としてアクセスできるようにするためには var a = new Array(N1 + 1); と宣言しなくてはならない。これは JavaScript の配列がゼロオリジンであるため。

エラトステネスの篩(ふるい)では最小の素数 2 からスタートするため a[0]a[1] も必要ない。このため自然数 $i$ が素数か否かを判定する配列を a[i - 2] としてアクセスするようにすれば配列宣言は var a = new Array(N1 - 1); で済む。ただ,高々2つの要素をケチる代償として,配列のアクセスがほんの少しだけ複雑になってしまう。

逆に配列のアクセスをシンプルにするため,配列の要素を大きめに確保したとも言える。

奇数を配列に割り当てる場合

自然数 $N_1$ 以下の奇数最大値 $N_2$ を

N_2 = \cases{
N_1 & \(N_1\ \bmod 2 \ne 0\) \\
N_1 - 1 & \(N_1\ \bmod 2 = 0\)
}

とおく。整数 $j$ を用いて奇数 $m = 2j + 1$ とおく。奇数 $m$ の範囲 $1 \le m \le N_2$ であり,整数 $j$ の範囲は $0 \le j \le (N_2 - 1) / 2$ となる。奇数 $m = 2j + 1$ が素数かどうかの判定用配列 a[j] を考えると,配列のサイズは $1 + (N_2 - 1) / 2$` となる。

なお,筆者の前回の記事では配列のサイズを $1 + [N_1/2]$ としていたが,これは誤っていた。具体例を挙げると分かり易い。

$N_1$ $N_2$ $1 + [N_1 / 2]$ $1 + (N_2 - 1) / 2$
$100$ $99$ $51$ $\color{red}{50}$
$101$ $101$ $51$ $51$
$102$ $101$ $52$ $\color{red}{51}$
$103$ $103$ $52$ $52$

ということで少し多めに確保していたことが分かる。

連続する8個の奇数をビット毎に割り当てする場合

前回の自分の記事のコメント欄にて,1つの奇数が素数か否かを保持するフラグにわざわざ1バイト使うのは勿体ない。8つの奇数をビット毎にまとめて1バイトで保持できるのではないか?という提案を受けた。こうすると必要な配列のサイズの計算はますます複雑になる。

配列に必要なサイズは表にまとめて整理すると分かり易い。

ここで奇数 $m = 2j+ 1$ を示す $j$ の最大値 $N_3 = (N_2 - 1)/2$ とおく。$1 \le m \le N_2$ かつ $0 \le j \le N_3$ である。

$N_1$ $N_2$ $N_3$ 配列のサイズ
$1 \le N_1 \le 16$ $1 \le N_2 \le 15$ $0 \le N_3 \le 7$ $1$
$17 \le N_1 \le 32$ $17 \le N_2 \le 31$ $8 \le N_3 \le 15$ $2$
$33 \le N_1 \le 48$ $33 \le N_2 \le 47$ $16 \le N_3 \le 23$ $3$
$49 \le N_1 \le 64$ $49 \le N_2 \le 63$ $24 \le N_3 \le 31$ $4$

必要なサイズは $1 + [(N_1 - 1) / 16]$ または $1 + [N_2 / 16]$ または $1 + [N_3 / 8]$ となる。

2,3の倍数を除いた自然数を配列に割り当てる場合

自然数 $N_1$ 以下の奇数最大値 $N_2$ を

N_2 = \cases{
N_1 & \(N_1\ \bmod 2 \ne 0\) \\
N_1 - 1 & \(N_1\ \bmod 2 = 0\)
}

とおく。さらに$N_2$ 以下で3の倍数でない奇数最大値 $N_3$ を

N_3 = \cases{
N_2 & \(N_2\ \bmod 3 \ne 0\) \\
N_2 - 2 & \(N_2\ \bmod 3 = 0\)
}

とおく。

2,3の倍数ではない自然数 $m$ を整数 $j, k$ を用いて $m = 6j + 2k - 1$ と表す。$j \ge 1$,$k = \lbrace 0, 1 \rbrace$ である。この $m$ が素数か否かの判定フラグを格納する配列 a[i] とすると,$i = 2j + k$ となる。すなわり $m = 6j + 2k - 1$ は $i =2j + k$ 番目の要素となる。

$j$ $i = 2j + k$ $m = 6j + 2k - 1$
$k = 0$ $k = 1$ $k = 0$ $k = 1$
$0$ $0$ $1$ $-1$ $1$
$1$ $2$ $3$ $5$ $7$
$2$ $4$ $5$ $11$ $13$
$3$ $6$ $7$ $17$ $19$
$4$ $8$ $9$ $23$ $25$
$5$ $10$ $11$ $29$ $31$
$6$ $12$ $13$ $35$ $37$

配列 a[] のサイズは $N_3$ によって決まる。$N_3 \bmod 3 = 1$ の場合と $N_3 \bmod 3 = 2$ の場合に分けて考える。

  • $N_3 \bmod 3 = 1$ の場合 $k = 1$ であり,配列のサイズは $2 + (N_3 - 1) / 3$ となる。
  • $N_3 \bmod 3 = 2$ の場合 $k = 0$ であり,配列のサイズは $2 + (N_3 - 2) / 3$ となる。

具体例を挙げると分かり易い。たとえば $N_3 = 35$ のとき,$k = 0$ なので配列のサイズは $2 + (35 - 2)/3 = 13$ 個となる。また $N_3 = 31$ のとき,$k = 1 $ なので配列のサイズは $2 + (31 - 1)/3 = 12$ 個となる。

以上をまとめると配列のサイズは $2 + (N_3 - N_3 \bmod 3) / 3 = 2 + [N_3/3]$ となる。

このような配列 a[] の大きさを前々回の記事では $2 + [N_1 / 3]$ として割り当てていたが,こちらも少し多めに割り当てていたことが分かった。

$N_1$ $N_2$ $N_3$ $2 + [N_1/3]$ $2 + [N_3/3]$
$100$ $99$ $97$ $35$ $\color{red}{34}$
$101$ $101$ $101$ $35$ $35$
$102$ $101$ $101$ $36$ $\color{red}{35}$
$103$ $103$ $103$ $36$ $36$
$104$ $103$ $103$ $36$ $36$
$105$ $105$ $103$ $37$ $\color{red}{36}$
$106$ $105$ $103$ $37$ $\color{red}{36}$
$107$ $107$ $107$ $37$ $37$
$108$ $107$ $107$ $38$ $\color{red}{37}$
$109$ $109$ $109$ $38$ $38$
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?