web-dev-qa-db-ja.com

フロートを最大/最小値に初期化するにはどうすればよいですか?

Floatまたはdoubleの絶対最大値または最小値をハードコーディングするにはどうすればよいですか?単純に最大値を反復処理してキャッチすることで、配列の最大値/最小値を検索したいと思います。

フロートには正と負の無限大もありますが、代わりにそれらを使用する必要がありますか?もしそうなら、どのようにコードでそれを示すのですか?

90
Faken

std::numeric_limitsで定義されている <limits> を使用して、タイプの最小値または最大値を見つけることができます(タイプに特化が存在する場合)。また、無限大を取得するために使用することもできます(そして負の無限大の前に-を置きます)。

#include <limits>

//...

std::numeric_limits<float>::max();
std::numeric_limits<float>::min();
std::numeric_limits<float>::infinity();

コメントに記載されているように、min()は可能な限り低い正の値を返します。言い換えれば、0に最も近い正の値を表すことができます。可能な最小値は、最大値の負の値です。

もちろん、 std::max_element およびmin_element関数(<algorithm>で定義)があります。これらの関数は、配列内の最大値または最小値を見つけるのに適した選択肢です。

141
Yacoby

最大の負の数には-FLT_MAX(または-DBL_MAX)を使用し、正の数にはFLT_MAX(またはDBL_MAX)を使用できます。これにより、可能性のあるfloat(またはdouble)値の範囲が与えられます。

おそらくFLT_MINを使用したくないでしょう。これは、floatで表現できる最小の正の値に対応し、floatで表現できる最も負の値ではありません。

FLT_MINおよびFLT_MAXは、std::numeric_limits<float>::min()およびstd::numeric_limits<float>::max()に対応しています。

37
MSN

配列内の最小/最大を見つけるために、可能な限り最小/最大に初期化する必要はありません。

double largest = smallest = array[0];
for (int i=1; i<array_size; i++) {
    if (array[i] < smallest)
        smallest = array[i];
    if (array[i] > largest0
        largest= array[i];
}

または、複数回行う場合:

#include <utility>

template <class iter>
std::pair<typename iter::value_type, typename iter::value_type> find_extrema(iter begin, iter end) {
    std::pair<typename iter::value_type, typename iter::value_type> ret;
    ret.first = ret.second = *begin;
    while (++begin != end) {
        if (*begin < ret.first)
           ret.first = *begin;
        if (*begin > ret.second)
           ret.second = *begin;
   }
   return ret;
}

サンプルコードを提供することの不利な点-他の人がすでに同じ考えを提案しているのを見ます。

標準にはmin_elementとmax_elementがありますが、これらを使用するにはデータを2回スキャンする必要があり、配列が大きい場合は問題になる可能性があります。最近の標準では、上記のstd::minmax_elementと同じことを行うfind_extremaを追加することでこれに対処しています(単一パスでコレクション内の最小要素と最大要素の両方を見つけます)。

編集:符号なしの配列でゼロ以外の最小値を見つける問題に対処します:符号なしの値が極端に達すると「ラップアラウンド」することを確認します。ゼロ以外の最小値を見つけるために、比較のためにそれぞれから1を引くことができます。値がゼロの場合、そのタイプで可能な最大値に「ラップアラウンド」されますが、他の値との間の関係は保持されます。完了したら、明らかに見つけた値に1を追加します。

unsigned int min_nonzero(std::vector<unsigned int> const &values) { 
    if (vector.size() == 0)
        return 0;
    unsigned int temp = values[0]-1;
    for (int i=1; i<values.size(); i++)
        if (values[i]-1 < temp)
            temp = values[i]-1;
    return temp+1;
}

これはまだ初期値に最初の要素を使用しますが、「特別なケース」コードは必要ありません。可能な最大値に折り返されるため、ゼロ以外の値は小さいと比較されます。結果は、ゼロ以外の最小値、またはベクトルにゼロ以外の値が含まれていない場合にのみ0になります。

17
Jerry Coffin

配列の最小値を手動で見つけるために、floatの最小値を知る必要はありません。

float myFloats[];
...
float minimum = myFloats[0];
for (int i = 0; i < myFloatsSize; ++i)
{
  if (myFloats[i] < minimum)
  {
    minimum = myFloats[i];
  }
}

最大値の同様のコード。

5
Bill

「これまでの最大と最小」変数を無限ではなく、配列の最初の数に初期化することをお勧めしますか?