1.10 整数除算(商+剰余, 標準 C ライブラリの汎用版)
標準 C ライブラリには、div または ldiv という、整数除算における商と剰余を対にした構造体を返す関数があります。C99 では、これらに加えて、lldiv という long long 型版の関数と、imaxdiv という intmax_t 型版の関数が用意されています。
では、C++ではどうかというと、div および ldiv がそのまま提供されているほか、long 型版の div が多重定義されています。これにより、実引数が int 型か long 型かを気にすることなく、単に std::div(a, b).quot または std::div(a, b).rem と記述すれば、適切な関数が呼び出されます。
しかし、関数名は多重定義されていますが、返却型は依然として div_t および ldiv_t ですので、テンプレートの中で使うには不向きです。そこで、結果を格納する構造体もテンプレートにしてみることにしました。
template<class T>
struct div_t
{
T quot;
T rem;
};
template<class T, bool Integer>
struct div_helper
{
static div_t<T> op(T numer, T denom)
{
div_t<T> result;
result.quot = numer / denom;
result.rem = numer % denom;
return result;
}
};
template<class T>
struct div_helper<T, false>
{
static div_t<T> op(T numer, T denom)
{
div_t<T> result;
result.quot = numer / denom;
std::modf(result.quot, &result.quot);
result.rem = numer - result.quot * denom;
return result;
}
};
template<class T>
div_t<T> div(T numer, T denom)
{
return div_helper<T, std::numeric_limits<T>::is_integer>::op(numer, denom);
}
div_t や div といった識別子は、本来 std 名前空間の中で宣言されるべきものですから、名前の衝突は起こらないはずなのですが、現実にはそうなっていない実装も多く、名前が衝突してしまいます。使用される場合は、適当な名前空間の中に入れるか、名前を変更してみてください。
なお、符号付き整数型で、一方が正、他方が負の場合の結果は処理系に依存するわけですが、C99 では結果が固定されたことからもわかるように、すでに div 関数と同等の振る舞いを処理系しか実在しないものと考えてもよさそうです。というわけで、今回は、シンプルに / と % を使って実装してみました。このように、連続してオペランドを用いて除算と剰余算を行うと、うまく最適化されることも多いようなので、あえてこのようにしています。
また、今回のオマケ的として、符号小数点数の商と剰余にも対応するようにしてみました。その他、必要に応じて、div 関数を多重定義すれば、BCD 演算クラス用のものや、固定小数点数クラス用のものも、同じシンタックスで使えるようになるはずです。
元ネタ
ブックナビゲーション
- 技術情報
- Boost C++ Libraries メモ
- C++と組込み環境
- C++サンプル集
- C++テンプレート集
- 1. 整数型に関するテンプレート
- 1.1 指定された整数型が符号付きか否かを判定する。
- 1.2 指定された整数型が 2 の補数表現か否かを判定する。
- 1.3 指定された整数型が1の補数表現か否かを判定する。
- 1.4 指定された整数型が「符号ビット+絶対値」か否かを判定する。
- 1.5 指定された整数型が表現可能な最小値および最大値を返す。
- 1.6 各種整数型の仕様を調べるテストプログラム
- 1.7 整数除算で端数切り上げ(商のみ)
- 1.8 整数除算で端数切り上げ(商+剰余)
- 1.9 整数除算で端数切り下げ(商+剰余)
- 1.10 整数除算(商+剰余, 標準 C ライブラリの汎用版)
- 1.11 最大公約数を求める。
- 1.12 無符号整数の最下位の '1' のビットだけを抽出する。
- 2. 数値型に関するテンプレート
- 3. 配列に関するテンプレート
- 4. 構造体に関するテンプレート
- 5. 一般のデータ型に関するテンプレート
- 6. メモリ上のデータ操作テンプレート
- 7. 文字・文字列・文字コードに関するテンプレート
- 8. 入出力に関するテンプレート
- 9. エンディアンに関するテンプレート
- 10. 日付・グレゴリオ暦計算テンプレート
- 11. 双方向線型リスト処理テンプレート
- 101. 整数型に関するテンプレート(オリジナル)
- 102. 文字種別に関するテンプレート(オリジナル)
- 103. 入出力に関するテンプレート(オリジナル)
- 1. 整数型に関するテンプレート
- C++プログラマのためのC言語入門
- C/C++迷信集
- C99関数・マクロ・前処理スクリプト集
- C言語再入門
- C言語徹底入門
- Drupal メモ
- TOPPERS 情報
- ベターCとしてのC++
- マイコン メモ
- ライブラリ開発入門
- 分割コンパイルをきわめる
- 擬似プロセッサを作る
- 象の卵を探して...
- 車輪の再発明
- 過去の情報

