4

我正在尝试23.40使用以下方法转换以双精度表示的时间,例如表示 23 小时 40 分钟:

private TimeSpan DoubleToTimeSpan(double time)
{
    double hour = Math.Floor(time);
    double minute = (time - hour) * 100d;
    TimeSpan ts = new TimeSpan((int)hour, (int)minute, 0);
    return ts;
}

在某些时候对其进行测试时,23.40例如:

Console.WriteLine(DoubleToTimeSpan(23.40));

显示23:39:00,整整一分钟都被系统偷走了!我的分钟在哪里?

注意:我知道TimeSpan.FromHours,这对我没有帮助,因为这种方法将分钟视为百分比,因此23.4023 小时和一小时的 40%,即23:24:00.

4

7 回答 7

9

由于0.4无法以Double浮点格式精确表示,因此您会得到最接近的表示形式,在这种情况下(23.4-23)*100可能类似于39.999999999999858. 使用 时(int),会截断分数,留下 39。

您需要舍入而不是截断,所以使用(int)Math.Round(minute).

或者,您可以使用可以精确表示十进制数字的Decimal类型,例如.23.40

于 2013-08-02T12:58:14.113 回答
2

尝试舍入它而不是 int

private TimeSpan DoubleToTimeSpan(double time)
{
    double hour = Math.Floor(time);
    hour.Dump();
    double minute = (time - hour) * 100d;
    minute.Dump();
    TimeSpan ts = new TimeSpan((int)hour, (int)Math.Round(minute), 0);
    return ts;
}

如果你只做 (int)minute 它将占用你的双倍的整数部分。

于 2013-08-02T12:57:03.337 回答
0

当您从 adouble转换为 a 时int,它会截断您的分钟值 - 因此您失去的分钟。

于 2013-08-02T12:57:43.333 回答
0
(time - hour) * 100d

将评估为 39.999999999999858,因此在转换为 int 时为 39。

于 2013-08-02T12:59:03.350 回答
0

您已经使用了 Math.Floor 一个小时,所以请使用 Math.Ceiling 一分钟。它似乎工作正常。

private static TimeSpan DoubleToTimeSpan(double time)
{
    return new TimeSpan((int)Math.Floor(time), (int)Math.Ceiling((time - Math.Floor(time)) * 100d), 0);
}
于 2013-08-02T13:02:59.617 回答
0

使用小数的另一种选择。这将防止精度损失。

decimal minute = ((decimal)time)-((decimal)hour)*100;
于 2013-08-02T13:06:54.827 回答
0

不确定这是否是更好的解决方案,但如果您使用的是 .NET 4.0 或更高版本,您也可以通过string. 似乎"23.40"是一个字符序列,一个解释为 a double,另一个解释为 a TimeSpan

如果您喜欢这个想法,请使用:

TimeSpan DoubleToTimeSpan(double time)
{
    string str = time.ToString("F2", CultureInfo.InvariantCulture);
    TimeSpan ts = TimeSpan.ParseExact(str, "h'.'mm", CultureInfo.InvariantCulture);
    return ts;
}

可能不如乘以 100 和四舍五入的方法快,尽管我还没有测试过。

于 2013-08-02T13:17:30.470 回答