以安全的方式乘以分数c#

以安全的方式乘以分数c#,c#,winforms,numeric,C#,Winforms,Numeric,我试图找出如何以数字安全的方式计算出车辆维修工作的总成本,避免四舍五入错误。我得到了在一项工作上花费的时间,然后乘以一个固定的人工费率值,得到了正确的人工成本,但它并没有计算出它应该是多少。这是我的例子,在工作上花了20分钟 这显然是错误的,因为30英镑的三分之一是10英镑,那么如何避免我得到的舍入误差呢 这是我得到总时间的方法 TimeSpan totalTime = TimeSpan.Zero; foreach (DataRow timeEntry in dhJob.DataSt

我试图找出如何以数字安全的方式计算出车辆维修工作的总成本,避免四舍五入错误。我得到了在一项工作上花费的时间,然后乘以一个固定的人工费率值,得到了正确的人工成本,但它并没有计算出它应该是多少。这是我的例子,在工作上花了20分钟

这显然是错误的,因为30英镑的三分之一是10英镑,那么如何避免我得到的舍入误差呢

这是我得到总时间的方法

TimeSpan totalTime = TimeSpan.Zero;

    foreach (DataRow timeEntry in dhJob.DataStore.Tables[jobTimeCollectionName].Rows)
    {
        DateTime start = Convert.ToDateTime(timeEntry["jobtimestart"]);
        DateTime end = Convert.ToDateTime(timeEntry["jobtimeend"]);
        totalTime += (end - start);
    }

    tb_labourtime.Text = Convert.ToString(Math.Round(totalTime.TotalHours, 2));

    tb_labourtotal.Text = (Convert.ToDouble(tb_labourtime.Text) * Convert.ToInt32(tb_labourrate.Text)).ToString();

非常感谢您提供的任何帮助/建议。

首先,您正在将
totalTime
转换为一个字符串表示法,该字符串表示法只有两位数的精度,这将不会非常准确

其次,在进行财务计算时,通常应使用
decimal
类型,而不是
double
类型,这将使您获得更高的准确性(尽管它仍然不完全准确)

首先要做的是使用
totalTime
计算总工资,而不是使用转换后的字符串值:

tb_labourtotal.Text = (totalTime.TotalHours * Convert.ToInt32(tb_labourrate.Text)).ToString();

查看
decimal
类型。@Alex他正在将时间转换为一个只有两位精度的字符串,因此无论使用多少
decimal
都无法解决这个问题(但我同意他应该使用
decimal
作为解决方案的一部分-这不是整个解决方案),我认为你最好提供一种输入分钟的方法。虽然
0.33
看起来很接近,但与精确结果相比仍然是
0.0033333…
,这可能会影响舍入。@MatthewWatson-oops。我做了一个本能的评论,但没有很好地检查这个问题。
tb_labourtime.Text=Convert.ToString(…);Convert.ToDouble(tb_labourtime.Text)
这太脏了。这种风险转换不仅存在错误,而且很难理解和验证是否正确。非常感谢@MatthewWatson。我不知道转换为字符串时的精度损失。将double改为decimal,并停止转换文本数字类型,效果更好。再次感谢。