使用Math.Floor的意外结果

时间:2014-08-15 15:11:57

标签: c# math

我正在编写一个我需要处理mm和英寸的应用程序。我已经编写了一些简单的代码来缩放两个度量单位,我也有一些代码来取一个十进制数并将其转换为分数。但是,当我使用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();
        }
    }
}

2 个答案:

答案 0 :(得分:6)

双打不是十进制数的精确表示,它们用二进制数表示。它们不会精确转换为十进制数,因此您无法保证5 * 2.52 / 2.52等于5.0。我建议改用C#type Decimal。

修改

有关C#Decimal类型

的更多信息,请参阅this question

答案 1 :(得分: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的原因。