我在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);
dtpDateStart
,dtpTimeStart
,dtpDateEnd
和dtpTimeEnd
都是Win Forms项目中的日期时间选择器控件。
当我调试此代码时,我发现subtotalRounded
的返回值是2.1999999999999997或3.1999999999999997而不是2.2和3.2。这似乎不会发生在4小时12分钟或更长时间或1小时12分钟或更短时间内。
无论如何,我完全不知道为什么只有这两个值会发生舍入错误。有没有人有任何建议或意见?我是否错误地使用了该方法,或者有更好的方法吗?
答案 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会导致浮点错误。感谢所有帮助新程序员的人!