毫秒精度的TimeSpan比较

4

我在这里遇到了一些奇怪的问题,但我不确定是因为我对TimeSpan APIs的理解有误。以下内容会输出false,但我不确定原因:

var foo = TimeSpan.FromMilliseconds(123.34d);
var bar = TimeSpan.FromMilliseconds(123.33d);
Console.WriteLine(foo > bar);

以下代码将打印出true:
var foo = TimeSpan.FromMilliseconds(123.34d);
var bar = TimeSpan.FromMilliseconds(123.33d);
Console.WriteLine(foo == bar);
< p>在进行比较时,TimeSpan.FromMilliseconds是否考虑毫秒精度?


我在 Linqpad 中执行了这两个,它们都以 00:00:00.1230000 的形式转储到控制台。 - Stephen Kennedy
1
当您在调试器中查看变量之一时,其真实值是什么? - lboshuizen
1
可能是重复的问题:TimeSpan FromMilliseconds奇怪的实现? - Stephen Kennedy
2
MSDN网站中,备注部分指出:“值参数将被转换为滴答数,并使用该数量的滴答数初始化新的TimeSpan。因此,值仅被认为是最接近毫秒的准确值。” - Michael
1
值已经四舍五入。请查看https://dev59.com/H2445IYBdhLWcg3w1tqi - Polhovskiy
4个回答

5

TimeSpan 只是简单地将传递给它的毫秒数四舍五入,因此 123.33123.34 都表示 123 毫秒的时间跨度。123.5 将被四舍五入为 123 毫秒。

如果需要更好的精度,请自己使用刻度计算:

var foo = TimeSpan.FromTicks((long)(123.34*TimeSpan.TicksPerMillisecond));
var bar = TimeSpan.FromTicks((long)(123.33*TimeSpan.TicksPerMillisecond));
Console.WriteLine(foo > bar);

现在你的程序输出True演示链接)。

1
根据API文档http://msdn.microsoft.com/en-us/library/system.timespan.frommilliseconds(v=vs.110).aspxTimeSpan.FromMilliSeconds(double d)方法接受任何双精度浮点数,但仅考虑小数点后一位的值因为在使用TimeSpan结构体之前,双精度浮点数将被转换为滴答数

该值参数会被转换为滴答数,且滴答数会用于初始化新的TimeSpan。因此,value将只被认为是最近的毫秒值。注意,由于Double数据类型的精度损失,当值接近MinValue或MaxValue范围内时,这种转换可能会生成OverflowException异常。

该网站上的示例也强调了这一点:

GenTimeSpanFromMillisec(1);
GenTimeSpanFromMillisec(1.5);
GenTimeSpanFromMillisec(12345.6);
GenTimeSpanFromMillisec(123456789.8);
GenTimeSpanFromMillisec(1234567898765.4);
GenTimeSpanFromMillisec(1000);
GenTimeSpanFromMillisec(60000);
GenTimeSpanFromMillisec(3600000);
GenTimeSpanFromMillisec(86400000);
GenTimeSpanFromMillisec(1801220200);

0

Timespan接受浮点数作为毫秒的参数,但会忽略小数部分。

这是有道理的,因为timespan没有子毫秒的概念;它是最小的单位。


0

这是一个精度问题:

var fooba = TimeSpan.FromMilliseconds(123.36d);
var foob = TimeSpan.FromMilliseconds(123.35d);
var foo = TimeSpan.FromMilliseconds(123.34d);
var bar = TimeSpan.FromMilliseconds(123.33d);
Console.WriteLine(fooba + " > " + foob + "?: " + (fooba > foob));
Console.WriteLine(foob + " > " + foo + "?: " + (foob > foo));
Console.WriteLine(foo + " > " + bar + "?: " + (foo > bar));
Console.WriteLine(fooba + " == " + foob + "?: " + (fooba == foob));
Console.WriteLine(foob + " == " + foo + "?: " + (foob == foo));
Console.WriteLine(foo + " == " + bar + "?: " + (foo == bar));

00:00:00.1230000 > 00:00:00.1230000?: False
00:00:00.1230000 > 00:00:00.1230000?: False
00:00:00.1230000 > 00:00:00.1230000?: False
00:00:00.1230000 == 00:00:00.1230000?: True
00:00:00.1230000 == 00:00:00.1230000?: True
00:00:00.1230000 == 00:00:00.1230000?: True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接