整数

整数 の Rust

1個の演習

整数について

整数は、小数部分を持たない数です。マシンの中では、2進数のビットの並びとして表現されます。

整数には、符号が付くものと付かないものがあります。符号の有無とは、その数が負であるかどうかを示すために、数のビットを1つ確保することを意味します。

整数にはすべてビット幅があり、これはその数を構成するビットの数のことです。これは、その整数型で表現できる最大値に影響します。

たとえば、最もよく使われる整数型の1つがu8です。符号なしの8ビット整数で、1バイトとして見覚えがあるかもしれません。最小値は0、最大値は255です。

Rustには12種類の整数プリミティブ型があり、ビット幅と符号の有無によって分かれています。

符号なし 符号付き
u8 i8
u16 i16
u32 i32
u64 i64
u128 i128
usize isize

整数のビット幅は、uまたはiのあとの数字で常に示されます。usizeとisizeは特別で、ターゲットマシン上でポインターと同じ幅を持ちます。つまり、64ビットアーキテクチャーではusizeとisizeは64ビット幅ですが、32ビットアーキテクチャーでは32ビット幅になります。

どれを使えばよいのでしょうか?

一般には、ただ何らかの数値を表したいだけならi32を使います。32ビットはオーバーフローする可能性が比較的低いほど広い範囲を持ち、符号付きの数のほうが符号なしの数より意外な挙動が少ないからです。i32はCのlong、Javaのintに相当します。数値リテラルを使い、型を明示的に指定しない場合は、デフォルトでi32になります。

バイナリーデータを扱うなら、バイト単位で扱うのがもっとも簡単です。&[u8]やVec<u8>を使います。

Rustは、コレクションのサイズとインデックスにusizeを使います。これは、コンピューターが理論上usize::MAXバイトのメモリしかアドレス指定できないため、それより大きなメモリ上のコレクションは存在し得ないからです。そのため、コレクションを大量に扱う場合にはusizeが役立ちます。

データが32ビット整数に収まらない場合は、64ビットまたは128ビット整数に広げることを検討しましょう。128ビット整数にも収まらない場合は、num-bigintが提供するような多倍長整数型を使えます。

16ビット整数はあまり一般的ではありませんが、特定のマイクロコントローラーをターゲットにする場合には役立ちます。

アプリケーションで負の値が有効なケースがないとわかっている場合は、符号付き整数ではなく符号なし整数を使うほうがよいでしょう。数を数える処理はよい例です。

整数同士の変換

Rustには暗黙の数値変換がありません。整数型の間でキャストする必要がある場合、基本的な方法が2つあります。asキーワードと、FromおよびTryFromトレイトです。

asキーワードを使うのは簡単です。expr as Typeと書きます。ただし、asによるキャストを使うときには、覚えておくべき注意点と細かい落とし穴がいくつかあります。

トレイトを使ったキャストは少し手間がかかりますが、より安全です。変換トレイトは、安全な場合にだけ実装されているからです。たとえば、i32はFrom<u8>、From<u16>、From<i8>、From<i16>を実装しています。これらの型で表現できる値はすべて、i32で表現できることが保証されています。使い方はi32::from(expr)やexpr.into()のようになります。ここでexprはこれらの型のいずれかに解決されます。i32はTryFrom<u32>、TryFrom<u64>、TryFrom<u128>、TryFrom<usize>、TryFrom<i64>、TryFrom<i128>、TryFrom<isize>も実装しています。これらの変換は、値に応じて明示的に成功するかオーバーフローするかのどちらかになります。これらを使うには、必要に応じてstd::convert::TryFromまたはstd::convert::TryIntoトレイトをインポートし、i32::try_from(expr)やexpr.try_into()を使います。ここでexprは適切な型に解決されます。

一般には、asによるキャストよりトレイトを使ったキャストのほうが好まれます。特に、より広い型からより狭い型へ変換する場合にそうです。トレイトを使ったキャストはasによるキャストよりごくわずかにコストが高いだけです。性能上の理由でasを使うのは、極端にホットなループでもない限り、割に合いません。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます