浮動小数点型(double型)の最小値
みなさんこんにちは、こんなしょうもない記事をもてくれる人は片手で数えれるほどしかいないと思います。
そんなみなさん、こんな疑問を抱いたことはないですか?
「浮動小数点型の中で最小の値ってなんだろう?」
と。 ないですかね? 私はないです。
いや、だってdouble.MinValue
という値があるじゃないですか。
ちなみに、皆さん答え分かりますか?そう、double.NegativeInfinity
がありますね
double.MinValue
は最小値なのに、double.NegativInfinity
は負の無限大だからいかなる定数よりも小さいはず。果たしてどちらが小さいのか。
ってわけで確認していきましょう。
最小値を出す上でいくつかの数字をピックアップ。
var array = new[] { 0, double.MinValue, double.MaxValue, double.Epsilon, double.PositiveInfinity, double.NegativeInfinity, double.NaN };
MaxValue
とかは間違いなく違うのですが、とりあえず入れておきます。
最小値の算出のために以下のメソッドを書きました。
private static double GetMin(double[] array) { var min = array[0]; for (int i = 1; i < array.Length; i++) if (array[i] < min) min = array[i]; return min; } private static double GetMin2(double[] array) { var min = array[0]; for (int i = 1; i < array.Length; i++) min = Math.Min(min, array[i]); return min; }
メソッドを二つ用意はしましたが、実行結果は同じになるはずです。
実行のコードは以下の通り。
Console.WriteLine($"Min by MyMethod1 : {GetMin(array)}"); Console.WriteLine($"Min by MyMethod2 : {GetMin2(array)}");
で、気になる実行結果は
Min by MyMethod1 : -∞ Min by MyMethod2 : NaN
あれ?
二つのメソッドで違う答えが出てきました。どういうことでしょう。
これは、Microsoftの設計理念として、NaN
はいかなる値よりも小さい値であるというものがあります。*1
ただし比較演算子を使用した場合は、NaN
は値を持たないので、常にfalse
を返すようになっています。*2
すなわち下記のmin1
とmin2
は違う結果になるわけです。
var val = doubel.NaN; var min1 = (val < min )? val : min; var min2 = Math.Min(val , min);
ほかの方法で最小値を出すと以下の通りになります。
var sortArray = array.ToArray(); Array.Sort(sortArray); Console.WriteLine($"Min by Sort : {sortArray.First()}"); Console.WriteLine($"Min by OrderBy : {array.OrderBy(p => p).First()}"); Console.WriteLine($"Min by Aggregate : {array.Aggregate((p, q) => Math.Min(p, q))}"); Console.WriteLine($"Min by Aggregate : {array.Aggregate((p, q) => q < p ? q : p)}"); Console.WriteLine($"Min by Min : {array.Min()}");
Min by Sort : NaN Min by OrderBy : NaN Min by Aggregate : NaN Min by Aggregate : -∞ Min by Min : NaN
double.NaN
はいろいろ特殊ですね。
double.NaN
の特異性についてもまた書きたいです。
試してないですが、float
も一緒だと思います。
ではまた。