3

次の C++ プログラムの出力は次のとおりです0.300000000000000040000

cout << setprecision(40) << (0.1 + 0.2) << endl;

ただし、次の C# コード:

System.Console.WriteLine("{0:F40}", 0.1+0.2);

...予期せず を出力0.3000000000000000000000000000000000000000しますが、(予想どおり) として評価さ0.1+0.2 == 0.3Falseます。

「4」はどこにあり、どのように出力できますか?

4

2 に答える 2

6

正確に 4 の後にゼロが必要かどうかは明らかではありませんが、 any の正確な 10 進数値を出力できるようにするコードがいくつかdoubleあります。

テストアプリとして:

using System;

class Test
{
    static void Main(string[] args)
    {
        double d1 = 0.1;        
        double d2 = 0.2;
        Console.WriteLine(DoubleConverter.ToExactString(d1 + d2));
        Console.WriteLine(DoubleConverter.ToExactString(0.3));
    }
}

結果:

0.3000000000000000444089209850062616169452667236328125
0.299999999999999988897769753748434595763683319091796875

ビルトインの .NET フォーマッタは、その時点で数字をいわば「信頼」できないという理由で、「4」を与えることを拒否しているのではないかと思います。それらは、実際に目指していた値にたまたま最も近い値に関連する単なるノイズです。

のドキュメントからSystem.Double

デフォルトでは、Double 値には 10 進数で 15 桁の精度が含まれますが、内部では最大 17 桁が維持されます。

于 2012-10-22T20:03:59.343 に答える
1

と言ったら何になるの?

System.Console.WriteLine("{0:R}", 0.1+0.2);

のようなフォーマット文字列"F40"は、文字列の末尾にゼロを追加するだけです。ただの と比較して、追加の精度は得られません"G"。一方、は、 からの文字列に近い数値とその数値を区別するために必要な場合 (およびその場合のみ)"R"に、2 桁の余分な数字 (または 2 桁の余分な数字の最後の桁が の場合は 1 桁) を明らかにします。0"G"

追加:フォーマット文字列が .NET でどのように機能するかをよりよく理解するには、次のコードを実行してみてください。

double a = BitConverter.ToDouble(new byte[] { 49, 51, 51, 51, 51, 51, 211, 63, }, 0);
double b = BitConverter.ToDouble(new byte[] { 50, 51, 51, 51, 51, 51, 211, 63, }, 0);
double c = BitConverter.ToDouble(new byte[] { 51, 51, 51, 51, 51, 51, 211, 63, }, 0);
double d = BitConverter.ToDouble(new byte[] { 52, 51, 51, 51, 51, 51, 211, 63, }, 0);
double e = BitConverter.ToDouble(new byte[] { 53, 51, 51, 51, 51, 51, 211, 63, }, 0);

Console.WriteLine("using G:");
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.WriteLine(c.ToString());
Console.WriteLine(d.ToString());
Console.WriteLine(e.ToString());
Console.WriteLine("using F40:");
Console.WriteLine(a.ToString("F40"));
Console.WriteLine(b.ToString("F40"));
Console.WriteLine(c.ToString("F40"));
Console.WriteLine(d.ToString("F40"));
Console.WriteLine(e.ToString("F40"));
Console.WriteLine("using R:");
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"));

ここでabcd、およびは、バイト配列から明らかな seとしての「隣人」です。、、、およびの場合にのみ、フォーマット文字列が余分な数字を与えるSystem.Doubleことがわかるはずです。の場合、余分な数字は必要ありませんが、17 の数字で書く場合、17 の最後の 2 つはそうではないことは明らかです(メソッドが .NET に組み込んだ完全な 10 進展開については、Jon Skeet の回答も参照してください)。簡単にはくれません)。"R"abdecc00

于 2012-10-22T20:53:47.523 に答える