ぬうぱんの備忘録

技術系のメモとかいろいろ

作った曲一覧はこちら

std::numeric_limits<float>::min()について重大な思い違いをしていた話

何があった

線形探索で最大値を探すコードを書いていた。
簡単化するとこんな感じ。

using namespace std;

float FindMax(const vector<float>& source)
{
	float max = numeric_limits<float>::min();	// floatの最小値で初期化してるつもり
	for(const auto& value : source)
	{
		if( max < value )
		{
			max = value; //maxは最小値で初期化してるから必ず一度はここを通るはず
		}	
	}
	return max;
}

でも動かしてみるとなんだか挙動がおかしい。
なんか負数しかないデータ列が来た時に一度もmaxが更新されない。
おかしいと思ってデバッガで初期値を見てみると「1.17549e-38」になってる。
よく見たら正の数なんですがそれは。

どういうことなのか

numeric_limit::min() は確かに「最小値」を返すんです。
でも浮動小数点に限っては「最小値」っていうのは「表現可能な中で絶対値的に最も小さい値」みたいなものを指してるんですね。
正確には「正の正規化数のうち最小のもの」みたいです。
なのでマイナスの絶対値がすごくでっかい値が帰ってくるわけではないんですね。

じゃあどうするのか

numeric_limits::lowest() を使いましょう。
こっちはちゃんと最小値を返してくれます。
ちなみに、qnan みたいな無効値で初期化すると max < value が必ず false と評価されるのでうまく行きません。