在.NET中将double转换为字符串不如C ++精确?

时间:2012-10-22 19:58:11

标签: c# floating-point double ieee

以下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.3评估为False

“4”在哪里,我该如何输出?

2 个答案:

答案 0 :(得分:6)

目前尚不清楚你是否希望完全 4后跟零,但我有some code这将允许你打印出任何{{1}的确切十进制值}。

所以作为测试应用程序:

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));
    }
}

我怀疑内置的.NET格式化程序拒绝给你“4”,因为在这一点上数字不能被“信任”。它们只是噪声相关的值,它恰好与您真正瞄准的值最接近。

来自System.Double的文档:

  

默认情况下,Double值包含15个十进制数字的精度,但内部最多保留17位数。

答案 1 :(得分:1)

如果你说

,你会得到什么?
System.Console.WriteLine("{0:R}", 0.1+0.2);

"F40"之类"G"只会在字符串末尾添加零。与仅"R"相比,它不会给您额外的精确度。另一方面,0将显示两个额外的数字(如果两个数字中的最后一个是额外的"G"则显示一个),如果(并且仅当)这是必要的,以区分数字和数字离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")); 的字符串更近。

添加:为了更好地了解格式字符串在.NET中的工作方式,请尝试运行以下代码:

a

此处,bcdeSystem.Double是“邻居”,"R" s字节数组。您应该会看到a格式字符串仅在bdec的情况下提供额外数字。对于c,不需要额外的数字,但很明显如果一个用{17}数字写00,那么17的最后两个不会是{ {1}}(另请参阅Jon Skeet对完整十进制扩展的回答,.NET中内置的方法不会轻易提供给您。)