【问题标题】:Printing increments of 0.1 in c#在 c# 中打印 0.1 的增量
【发布时间】:2010-10-27 10:32:32
【问题描述】:

我目前正在阅读 Steve McConnell 的 Code Complete,特别是关于浮点数的第 295 页。

当我运行以下代码时:

        double nominal = 1.0;
        double sum = 0.0;

        for (int i = 0; i < 10; i++)
        {
            sum += 0.1;
            Console.WriteLine("sum: " + sum.ToString());
        }

        if (equals(nominal,sum))
        {
            Console.WriteLine("Numbers are the same");
        }
        else
        {
            Console.WriteLine("Numbers are different");
        }

我打印出来了 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 数字不同

为什么我没有得到假设发生的输出? IE: 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.79999999999999999 0.89999999999999999 0.99999999999999999 数字不同

当我进行从双精度到字符串的隐式转换时,C# 是否对数字进行舍入?我是这么认为的,因为当我调试应用程序并逐步执行 for 循环时,我可以看到非终止的重复十进制数。你怎么看?我是对还是错?

【问题讨论】:

    标签: c# floating-point


    【解决方案1】:

    double.ToString() 使用通用格式,如果未指定精度,则默认为 15 位小数。所以它确实做了一点四舍五入,这就是为什么你看到你所看到的。例如,您在问题中指定的 0.89999999999999999 是小数点后 17 位。您实际上可以通过 sum.ToString("g17") 看到整个数字。

    您可以在此处找到 .net 的标准数字格式字符串及其默认精度:http://msdn.microsoft.com/en-us/library/dwhawy9k(VS.80).aspx

    【讨论】:

    • 啊,谢谢。我应该对我给你的输出非常精确。当我给出像 0.79999999999999999 这样的长十进制数字时,我并没有注意我使用的位数。
    【解决方案2】:

    它在 ToString 默认行为中。如果你在调试器中查看 sum,你会得到这个,它显示了没有通过 ToString 路由的值:

    0.0
    0.1
    0.2
    0.30000000000000004
    0.4
    0.5
    0.6
    0.7
    0.79999999999999993
    0.89999999999999991
    

    表明基本行为与您预期的一样。

    【讨论】:

      【解决方案3】:

      简短的回答是:它是浮点数,所以不要指望它是正确的(对于“正确”的合适值)!长答案是了解浮点如何工作以及人们如何使用浮点。 IIRC GNU printf(以及我认为的其他)特殊情况“真的非常接近一个不错的以 10 为底的数字”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多