浮動小数点の不正確さとc#での処理方法を理解しようとしています。
いくつかの良い答えを与える浮動小数点の不正確な例を見てきましたが、それを特にc#に理解したいと思います。
10進数の「8.8」を使用して、これを2進数表現に変換してから、10進数に戻し、その値が「8.8000000000000007」に変わるようにするにはどうすればよいですか。
運が悪ければ、C#でfloatのIEEE754バイナリ表現を取得する方法の提案を使用してみました。
浮動小数点の不正確さとc#での処理方法を理解しようとしています。
いくつかの良い答えを与える浮動小数点の不正確な例を見てきましたが、それを特にc#に理解したいと思います。
10進数の「8.8」を使用して、これを2進数表現に変換してから、10進数に戻し、その値が「8.8000000000000007」に変わるようにするにはどうすればよいですか。
運が悪ければ、C#でfloatのIEEE754バイナリ表現を取得する方法の提案を使用してみました。
ただし、これが問題です。8.8000000000000007もで正確に表すことはできませんdouble
。最も近い値は8.800000000000000710542735760100185871124267578125です(これはJon SkeetのDoubleConverterから取得しました)。次に、その文字列を使用Decimal.Parse
して、8.80000000000000071054273576の10進値を取得できます。
decimal d = 8.8M;
double dbl = (double)d;
string s = DoubleConverter.ToExactString(dbl);
decimal dnew = decimal.Parse(s);
あなたはこのようにいくつかの異なるダブルを比較することができます:
double a = BitConverter.ToDouble(new byte[] { 156, 153, 153, 153, 153, 153, 33, 64, }, 0);
double b = BitConverter.ToDouble(new byte[] { 155, 153, 153, 153, 153, 153, 33, 64, }, 0);
double c = BitConverter.ToDouble(new byte[] { 154, 153, 153, 153, 153, 153, 33, 64, }, 0);
double d = BitConverter.ToDouble(new byte[] { 153, 153, 153, 153, 153, 153, 33, 64, }, 0);
double e = BitConverter.ToDouble(new byte[] { 152, 153, 153, 153, 153, 153, 33, 64, }, 0);
Console.WriteLine(a.ToString("R"));
Console.WriteLine(b.ToString("R"));
Console.WriteLine(c.ToString("R"));
Console.WriteLine(d.ToString("R"));
Console.WriteLine(e.ToString("R"));
フォーマット文字列 を使用すると、"R"
余分な数字が表示されますが、他の表現可能なものを区別するために必要な場合に限りSystem.Double
ます。
加算(バイトの説明):64
そして33
、符号、大きさ、および数値の最初の(最上位)ビットを指定し8.8
ます。8.8
は分母が小さい分数(44/5の5)であるため、残りのビットが短い期間で何度も繰り返されることは驚くべきことではありません。正確に取得する8.8
には、153は永遠に継続する必要があります。ただし、には8バイトのスペースしかありませんdouble
。したがって、丸める必要があります。154
次の「項」(153
)は。256
よりも近いため、に丸めると最も近い値が得られ0
ます。したがってc
、可能な限り最も正確な表現です。
上記のコードの出力を見ると、フォーマット文字列を使用した場合でもc
出力されていることがわかります。しかし、それはとの中間(およびとの中間)であり、そこから「真の」10進値が最も近いと簡単に見積もることができます。8.8
"R"
c
b
d
a
e
8.8000000000000007