フロートの配列があり、最小から最大にソートされており、渡された入力値よりも大きいまたは小さい最も近いフロートを選択できる必要があります。この入力値は、必ずしも配列内の値として存在するわけではありません。
素朴なアプローチは、配列全体で単純な線形検索を行うことです。次のようになります。
void FindClosestFloatsInArray( float input, std::vector<float> array,
float *min_out, float *max_out )
{
assert( input >= array[0] && input < array[ array.size()-1 ] );
for( int i = 1; i < array.size(); i++ )
{
if ( array[i] >= input )
{
*min = array[i-1];
*max = array[i];
}
}
}
しかし、明らかにアレイが大きくなるにつれて、これはますます遅くなります。
このデータをより最適に見つけることができるアルゴリズムについて誰かが考えていますか?私はすでにバイナリ検索に切り替えましたが、問題が多少改善されましたが、それでもまだ思ったよりもかなり遅く、配列に存在する特定の値を実際に探しているわけではないため、終了することはできません早い。
詳細:配列内の浮動小数点値は必ずしも均等に分散されているわけではありません(つまり、配列は値「1.f、2.f、3.f、4.f、100.f、1200.fで構成されている可能性があります」 、1203.f、1400.f "。
この操作を何十万回も実行していますが、ルックアップ時間を改善する場合は、フロートの配列に対して任意の量の前処理を実行できます。それを助けるために、私はそれらを保存するためにベクトル以外のものを使うように絶対に変えることができます。
質問(線形検索)のコードは、あなたが正しく指摘しているように、大きなfloat配列では遅くなるでしょう。技術的には、O(n)です。nは配列内のfloat値の数です。
一般に、順序付けされた配列で値を見つけるためにできる最善の方法は、ある種の再帰ツリー検索(たとえば、バイナリ検索)です。この場合、要素数でO(log n)ルックアップ時間を達成できます。あなたの配列で。 O(log n)は、O(n)よりも大きいnの場合、muchよりも優れています。
したがって、私の提案するアプローチは、配列の単純なバイナリ検索です。つまり、
これはO(log n)アルゴリズムであり、ほとんどすべての状況で十分高速である必要があります。直感的には、正しい値が見つかるまで、各ステップで検索する範囲を半分にすることで機能します。
単純な二分探索を野蛮にするのは本当に難しいので、これをすでに正しく実装していれば、すでに最適にかなり近いかもしれません。ただし、データの分布がわかっている場合、またはルックアップ値(x)の範囲が限られている場合でも、さらに高度なトリックを試すことができます。
ただし、特別な状況でない限り、単純なバイナリ検索を使用することをお勧めします。理由:
これは十分に簡単なようです:
バインドするフロートのバイナリ検索を実行します-O(log n)時間。
次に、その左側の要素が下限であり、その右側の要素が上限です。
明白な答えは、フロートを tree に格納することです。 「前の」および「次の」操作をサポートすることは、ツリーでは簡単です。したがって、値に「次」を実行し、最初のステップで見つけた値に「前」を実行するだけです。