前回、定数といっても unsafe な奴を使ってしまったので、今後は unsafe でない constを使うべし、と思い定めました。さてconstな定数を使って配列を定義してみたところがエラー。Rustは、配列のサイズを宣言する際に定数の型すらもチェックしておるのでした。成り行きで配列を確保してるんじゃね~よ、と。
※「やっつけな日常」投稿順 Index はこちら
エラトステネスの篩
今回、Rustの練習で書いてみたのは、皆さまよ~くご存じの素数を求めるアレです。一つ素数が見つかったならばその倍数はすべて素数じゃない、と篩にかけるアレです。下から順番に見ていけば、篩の中に残っるのは素数だと。
今回、定番のサンプルプログラムとして16383までの素数を数え上げることといたしました。偶数は最初から篩の中に入れず、0、1、2も入らないので実際には8190個の整数(すべて奇数)を調べあげることになります。
素数か否かを記憶するbool型の配列を flags としてその初期値をとりあえず全部素数と仮置きの意味でtrueとし、篩で落とすたびにfalseに変えてまいりたいと思います。
配列宣言でエラー
いままでRustの配列を使っていなかったわけではないのですが、練習用の小さいプログラムなので、配列のサイズについては型など気にせずリテラルで書いてました。「どうせ整数型っしょ」という安易な考え。
今回、篩のサイズNを8190個にとりました。前回の件もあり const 宣言。サイズは「なんとなく」i32型としてみました。i16じゃすぐに尽きてしまうので、後々もう少し大きい数でもできるように程度の浅はかな考えです。こんな感じ。
しかし、Rustコンパイラからは厳しい指摘が飛んできます。エラー。こんな感じ。
i32型ではダメなのね。usize型? 調べてみるとusize型はターゲットマシン上での符合無のポインタのビットサイズのようです。メモリ上にとられる配列のサイズなので、その機種のアドレスサイズに合わせるということでしょうかねえ。合理的と言えば合理的。知らんけど。
実験に使用したソース
以下が、修正済のエラトステネスの篩のソースであります。Rustというわりには mut の変数が多くて汚い。
// Sieve of Eratosthenes const N: usize = 8190; fn sieve_of_eratosthenes() -> usize { let mut flags: [bool; N + 1] = [true; N + 1]; let mut count: usize = 1; let mut p: usize = 2; print!("{} ", p); for i in 0..=N { if flags[i] { p = i + i + 3; print!("{} ", p); let mut k = i + p; while k <= N { flags[k] = false; k += p; } count += 1; } } return count; } fn main() { println!("Sieve of Eratosthenes"); println!("----------------------------"); let count = sieve_of_eratosthenes(); println!("\n----------------------------"); println!("Number of primes < {}: {}", 2*N+3, count); }
実行結果
実行の末尾が以下に。16383までの整数の中で1900個の素数を見つけたようです。正解かね。多分。
Rust、配列サイズもなんとなくの整数値ではなかったのね。。。当然か。