ダブルスとINTの混合コレクションを保存する最も効率的な方法
-
21-09-2019 - |
質問
C ++にINTとダブルのコレクション(名目および実際の価値のあるデータを表す)を保存する必要があります。私は明らかにそれらをすべてに保存することができました std::vector<double>
、しかし、これは少し間違っていると感じ、美学のボーナスポイントを取得しません。
また、多型に基づいて何かを調理することもできますが、コレクションを非常に効率的にする必要もあります。コレクションのデータを保存して取得することの両方は、できるだけ早く保存する必要があります。このような解決策が最大効率的であるかどうかを判断するのは難しいと思います。
私も見つけました ブースト::バリアント, 、これはここで役立つかもしれません。
追加情報:コレクション内のアイテムの数は小さく(<100)、コレクションの初期化時に知られています。
要約:私は明らかにこれを無数の方法で解決することができましたが、(i)効率が本当に重要であり、(ii)やや素敵なコードを書きたいと思うとき、私は何が良い解決策であるか確信が持てません。ここでの私の最善の策は何ですか?
編集、追加情報: このコレクションは、より大きなデータセットの「行」を表し、その要素は特定の「列」の値を表します。行のプロパティは既知であるため、どの位置にどのようなデータが保存されているかがわかっています。私が話している「効率」は、主に特定の列のint/double値を取得する効率ですが、値の高速設定も重要です。できるだけ早く取得する必要があるデータで動作する機能がいくつかあります。例:
typedef std::vector<double> Row;
void doubleFun(Row const &row)
{
// Function knows there's always a double at index 0
double value = row[0];
...
}
void integerFun(Row const &row)
{
// Function knows there's always an integer at index 1
int value = row[1];
...
}
これまでにさらに考えて提案を読んだ後、2つの別々のベクトルにINTコラムと二重列を保存するだけであるように思われます。コレクション Row
次に、機能が使用できる名目データと実際のデータを取得するために、2つの異なるメンバーを定義できます。
aとして保存するだけです vector<double>
大丈夫だと思いますが、Doubleとintの間の変換がどれだけ速くなるかに依存します(おそらく非常に印象的です)。
最初は少し不明確になって申し訳ありませんが、それがより明確で、今では、この問題についてさらに考えを得ることができることを願っています。
解決
コンテナの重要なポイントを注文していますか?
そうでない場合:
class MyContainer
{
std::vector<double> doubles;
std::vector<int> ints;
push(double value) { doubles.push_back(value); }
push(int value) { ints.push_back(value); }
....
};
イテレーターの部分(容器全体を閲覧するため)は少し難しいかもしれません...
他のヒント
ダブルのベクトルを直接使用してみませんか?整数は精度を失うことなくダブルに変換できるため...最もシンプルで最も効率的なソリューションに見えます。
何が設定されるのか(そして、私はあなたの質問から理解できませんでした)、通常の値と実際の値の違いをどのようにすることができますか。問題は、選択する可能性のあるあらゆるソリューションで開いたままです。
ユニオンタイプを使用して、ベクトルでそれを使用できます。しかし、その場合、ベクトルのどの要素をINTとして扱うべきか、どの要素をダブルとして扱うべきかを知る方法が必要です。どのものがINTであり、どれが2倍であるかを追跡するには、ビットセットなどを使用できます。
あなたの目標が重い浮遊点計算を避けることであるかどうかはわかりません。もしそうなら、ビットセットがより効率的になる可能性があります。そうでない場合、そして正確なint精度は重要ではない場合、それらをすべてダブルとして保存することもできます。
#include <vector>
#include <bitset>
union di
{
double d;
int i;
};
int main(int argc, char* argv[])
{
std::bitset<2> bitsetInts;
std::vector<di> v;
di e1;
e1.d = 3.9;
v.push_back(e1);
di e2;
e2.i = 3;
bitsetInts.set(1);
v.push_back(e2);
return 0;
}
私はに行きます boost::variant
解決策、それはあなたのニーズに完全に適合します。
ブーストタプルがあります。コンパイル時にタイプを知っている場合に使用できます。しかし、アイテムの数が小さい場合、100バイトを無駄にするのに効率的には懸念されるべきではありません。