TimeSpan comparison with millisecond precision

2019-06-28 05:31发布

I'm hitting something here which is very odd but I'm not sure whether it's me knowing the TimeSpan APIs wrong. The following prints out false and I'm not sure why:

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

The following prints true:

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

Doesn't TimeSpan.FromMilliseconds take millisecond precision into account while doing the comparison?

标签: c# time
4条回答
成全新的幸福
2楼-- · 2019-06-28 06:04

Its an issue with precision:

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
查看更多
走好不送
3楼-- · 2019-06-28 06:12

TimeSpan simply rounds the number of milliseconds that you pass it, so both 123.33 and 123.34 end up representing a timespan of 123 milliseconds. 123.5 would be rounded up to 123 milliseconds.

If you need better precision, do the math with the ticks yourself:

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

Now your program produces True (demo).

查看更多
乱世女痞
4楼-- · 2019-06-28 06:21

Timespan accepts a floating point as a parameter for milliseconds but ignores the decimals.

Makes sense, as timespan has no notion of sub-milliseconds; it's the smallest unit.

查看更多
走好不送
5楼-- · 2019-06-28 06:29

According to the API documentation http://msdn.microsoft.com/en-us/library/system.timespan.frommilliseconds(v=vs.110).aspx the method TimeSpan.FromMilliSeconds(double d) takes any double value but only respects values up to one digit after the comma since the double is converted into ticks before it is used within the TimeSpan struct.

The value parameter is converted to ticks, and that number of ticks is used to initialize the new TimeSpan. Therefore, value will only be considered accurate to the nearest millisecond. Note that, because of the loss of precision of the Double data type, this conversion can generate an OverflowException for values that are near to but still in the range of either MinValue or MaxValue.

This is also emphasized by the examples on that site:

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

查看更多
登录 后发表回答