TimeSpan计算错误

时间:2017-12-26 23:27:58

标签: c# datetime numbers double

我在c#中创建了一小块软件,以十进制格式计算加班时间。我设计它使它总是向下舍入到最接近的十分之一小时。我遇到的问题是,当我尝试计算时间恰好是2小时12分钟或3小时12分钟时,我得到的结果不正确。相关代码如下:

   DateTime start = new DateTime(
                        dtpDateStart.Value.Year,
                        dtpDateStart.Value.Month,
                        dtpDateStart.Value.Day,
                        dtpTimeStart.Value.Hour,
                        dtpTimeStart.Value.Minute,
                        0);

        DateTime end = new DateTime(
            dtpDateEnd.Value.Year,
            dtpDateEnd.Value.Month,
            dtpDateEnd.Value.Day,
            dtpTimeEnd.Value.Hour,
            dtpTimeEnd.Value.Minute,
            0);

        TimeSpan subtotal = end - start;

        double subtotalRounded = subtotal.TotalHours;
        subtotalRounded = (Math.Floor(subtotalRounded * 10) / 10);

dtpDateStartdtpTimeStartdtpDateEnddtpTimeEnd都是Win Forms项目中的日期时间选择器控件。

当我调试此代码时,我发现subtotalRounded的返回值是2.1999999999999997或3.1999999999999997而不是2.2和3.2。这似乎不会发生在4小时12分钟或更长时间或1小时12分钟或更短时间内。

无论如何,我完全不知道为什么只有这两个值会发生舍入错误。有没有人有任何建议或意见?我是否错误地使用了该方法,或者有更好的方法吗?

4 个答案:

答案 0 :(得分:2)

使用double,它的位表示精确,而不是十进制表示。请改用decimal数据类型。 Microsoft声明:

  

避免在WHERE子句搜索条件中使用float或real列,   特别是=和<>运营商。最好限制浮动和真实   列到>或者<比较。

更改这两个代码行

double subtotalRounded = subtotal.TotalHours;
subtotalRounded = (Math.Floor(subtotalRounded * 10) / 10);

到此:

decimal subtotalRounded = subtotal.TotalHours; // See data type!
subtotalRounded = (Math.Floor(subtotalRounded * 10) / 10);

甚至更短:

decimal subtotalRounded = = (Math.Floor(subtotal.TotalHours * 10) / 10);

您可能需要进行正确的数据类型转换。如果是这样,您可以使用Convert类中的辅助方法。

答案 1 :(得分:0)

这就是浮点值的工作方式,通常是在显示时而不是在计算时处理它。那就是当你执行string.Format(" {0:f2}",value)时,它将会舍入到所请求的位数。

答案 2 :(得分:0)

某些数字无法在double中准确表示。您应该使用decimal或(最好)在几分钟内工作,然后在输出时使用decimal除以60。

答案 3 :(得分:0)

你对浮点数没问题。我将所有内容转换为十进制,现在可以使用了我确信有更优雅的方法可以做到这一点,但这是我的代码:

        DateTime start = new DateTime(
                        dtpDateStart.Value.Year,
                        dtpDateStart.Value.Month,
                        dtpDateStart.Value.Day,
                        dtpTimeStart.Value.Hour,
                        dtpTimeStart.Value.Minute,
                        0);

        DateTime end = new DateTime(
            dtpDateEnd.Value.Year,
            dtpDateEnd.Value.Month,
            dtpDateEnd.Value.Day,
            dtpTimeEnd.Value.Hour,
            dtpTimeEnd.Value.Minute,
            0);

        TimeSpan subtotal = end - start;

        decimal decSubtotalMinutes = Convert.ToDecimal(subtotal.TotalMinutes);
        decSubtotalMinutes = decSubtotalMinutes / 60;
        decSubtotalMinutes = (Math.Floor(decSubtotalMinutes * 10) / 10);

使用小数可以正确计算出来。我不知道使用double会导致浮点错误。感谢所有帮助新程序员的人!