範囲内のどこかにある値を表す整数のようなクラスを作成しています。たとえば、 の値はbounded::integer<0, 10>
[0, 10] の範囲内にあります。このクラスでは、 と定義radix
しました2
。
の値は何であるべきdigits
ですbounded::integer<-100, 5>
か?
どうbounded::integer<16, 19>
ですか?
標準をもう少し読んでこれについて考えた後、私は最良の答えを持っていると信じていますが、確かではありません.
最初に、digits
最新の C++14 ドラフト標準、N3797、§ 18.3.2.4 から取得した の定義:
static constexpr int digits;
8
radix
そのまま表現できる桁数。9 整数型の場合、表現内の符号なしビットの数。
10 浮動小数点型の場合
radix
、仮数部の桁数
の場合は の場合とbounded::integer<-100, 5>
同じでbounded::integer<0, 5>
、値は になり2
ます。
の場合、bounded::integer<16, 19>
としてdigits
定義する必要があります0
。このようなクラスは 1 ビットの数値を表すことさえできず (0
と1
が範囲内にないため)、18.3.2.7.1 によれば:
すべてのメンバーは、すべての専門分野に提供されるものとします。ただし、多くの値は特定の条件下で
epsilon()
のみ意味を持つ必要があります (たとえば、 が意味を持つのは の場合だけis_integer
ですfalse
)。「意味がない」値は、0 または false に設定されます。
0
可能な値として持たない整数のようなクラスは、 and を意味のある形で計算できないと私は信じていdigits
ますdigits10
。
別の考えられる答えは、数字の情報理論的定義を使用することです。ただし、これは組み込み整数の値と一致しません。説明では明示的に符号ビットを除外していますが、それでも 1 ビットの情報と見なされるため、この解釈は除外されていると思います。この符号ビットの除外は、最初の数値の範囲の負の端と正の端のうち小さい方をとらなければならないことも意味しているようbounded::integer<0, 5>
です。これは、データを失うことなく 2 ビットしか格納できないことが保証されているためです。数値が負である限り最大 6 ビットを格納できる可能性がありますが、一般的には 2 ビットしか取得できません。
bounded::integer<16, 19>
ははるかにトリッキーですが、「意味がない」という解釈は、値をシフトして、あたかも でbounded::integer<0, 3>
あるかのように同じ答えを与えるよりも理にかなっていると思います2
。
この解釈は標準に従っており、他の整数型と一致しており、そのようなクラスのユーザーを混乱させる可能性が最も低いと思います。
の使用例の質問に答えるためにdigits
、コメンターは基数ソートに言及しました。基数 2 の基数の並べ替えでは、値を使用して数値を並べ替えることが期待される場合がありますdigits
。このような基数ソートを使用しようとした場合のエラー状態を示すため、 に設定digits
して0
も問題ありませんが、組み込みの型に沿ったまま、より良い処理を行うことはできますか?
符号なし整数の場合、 の値に依存する基数ソートはdigits
問題なく機能します。uint8_t
持っていdigits == 8
ます。ただし、符号付き整数の場合、これは機能しません: std::numeric_limits<int8_t>::digits == 7
. また、その符号ビットでソートする必要がありますが、そうするのdigits
に十分な情報が得られません。
あなたはそれを考えすぎています。digits
独自のスペシャライゼーションには 2 つの簡単なオプションがありますranged_integer
log2(Last-First)
範囲を表している場合[First, Last)
。N * numeric_limits<U>::digits
最小の基になるストレージに対応します。std::array<U, N>
符号ビットなどを気にする必要がないように、クラスranged_integer
は内部的に変換を行って、たとえばの範囲をマップできること[-100, 5]
に注意してください。[0, 105]