【问题标题】:Unexpected result using Math.Floor [duplicate]使用 Math.Floor 的意外结果 [重复]
【发布时间】:2014-10-09 08:13:30
【问题描述】:

我正在编写一个需要处理毫米和英寸的应用程序。我编写了一些简单的代码来在两个度量单位之间进行缩放,并且我还有一些代码来获取十进制数并将其转换为分数。但是,当我使用 Math.Floor 从小数中拆分整数时,我发现我并不总是得到返回的预期值。我附上了一些代码来演示这个问题。我希望最终结果是 6,但我得到了 5。我很难理解为什么。有什么想法吗?

// This is a .Net 4.5 console application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            double ValA = 6;
            double ValB = 0;
            double ValC = 0;
            double ValD = 0;

            ValB = ValA * 25.4;

            ValC = ValB / 25.4; 

            ValD = Math.Floor(ValC);

            Console.WriteLine(ValA.ToString());
            Console.WriteLine(ValB.ToString());
            Console.WriteLine(ValC.ToString()); // This returns 6 as expected
            Console.WriteLine(ValD.ToString()); // But this returns 5.

            Console.ReadKey();
        }
    }
}

【问题讨论】:

  • 重复:非常多。不好的问题:一点也不。 Upvote/downvote 论点:Stackoverflow 永远无法解决的问题,但社区 :)

标签: c# math


【解决方案1】:

双精度数不是十进制数的精确表示,它们用二进制基数表示。它们不能完全转换为十进制数,因此您不能保证 5 * 2.52 / 2.52 等于 5.0。我建议改用 C# 类型的 Decimal。

编辑

有关 C# Decimal 类型的更多信息,请参阅this question

【讨论】:

    【解决方案2】:

    这一行的打印输出

    Console.WriteLine(ValC.ToString());
    

    具有误导性:I/O 库打印 6,即使实际值略小于 6:

    Console.WriteLine(ValC < 6.0);
    

    上面的行打印True,这是有道理的:在乘以和除以相同的数字后累积的微小错误会妨碍。

    根据 IEEE-754 计算器,25.4 表示为 25.399999618530273。在乘除之后,有一个微小的差异,大约为8E-16,但你得到的值略小于6。这就是Floor正确返回5的原因。

    【讨论】:

      猜你喜欢
      • 2013-02-19
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 2017-10-04
      • 2014-12-01
      • 1970-01-01
      • 2013-04-03
      • 2018-05-31
      相关资源
      最近更新 更多