为什么AddMilliseconds方法会舍入双精度参数?

8
DateTime.Now.AddMilliseconds(1.5); // adds 2 milliseconds

这到底是怎么想的?如果一个方法不能处理小数部分,却接受double参数,这种做法看起来极其糟糕。为什么不用AddTicks函数并正确处理小数呢?或者至少采用int类型参数,这样对调用方更透明?
我猜他们采用这种方式肯定有好的原因,但我无法想出是什么。有人可以提供任何见解吗?
编辑:为了进一步强调这一点:
AddSeconds(1.5); // Adds 1500 milliseconds

TimeSpan 的各种 From 工厂方法也会进行四舍五入,尽管其分辨率更高。我只能推测 CLR 团队认为这种四舍五入是开发人员所期望的。 - Richard
2
需要Eric Lippert的时候他在哪里啊? :) - Benjol
4个回答

5
这是一个妥协,不算完全不合理。传递的参数必须四舍五入以处理 DateTime 的分辨率。将精度舍入到计时周期(100 纳秒)会带来问题。Double 类型没有足够的有效数字来覆盖可能的全部日期范围。10000 年 x 365 x 24 x 3600 x 1000 x 10000 = 3E18,而 Double 类型只有 15 个有效数字。将精度舍入到毫秒并没有问题,3E14 刚刚好够用(几率有多大?)。
解决方法很简单,只需使用 AddTicks(1.5 * 10000)。

很好的解释!尽管如果我是微软团队的一员,我会选择在整个值范围的顶部进行修剪,因为并不是太多人会关注那么高的值,而且当他们确实关注时,他们应该意识到缺乏有效数字所面临的问题,并直接使用64位整数(或者必要时,128位)。 - Grant Peters
1
猜测:这是一个Interop问题。另一个选择是一个很长的但是对遗留代码支持不够好的解决方案。就像COM。 - Hans Passant

2

这似乎相当奇怪。我唯一的想法是,也许他们觉得将时间舍入到最接近的毫秒比风险调用者将double截断为int更好。是的,这是一个相当无力的解释。抱歉。


特别是看到如果他们只是要将其截断为int,那么他们应该将其作为这样传递,并强制开发人员显式转换他们的值。 - Grant Peters

1

DateTimeTimeSpan会进行一些舍入。但是,如果您知道Ticks是100纳秒间隔,则可以解决此问题:

var now = DateTime.Now;
var result = now + TimeSpan.FromTicks(10000 * 1.5);

1毫秒内有10,000个100纳秒间隔。

编辑:更正,DateTime存储的是*100*纳秒间隔(而不是10纳秒)。


-1

来自MSDN

毫秒值在添加到指定的DateTime之前会四舍五入为最接近的整数。

由于DateTime无法解析小于毫秒的任何内容,因此添加小数毫秒也是错误的做法。

我认为他们做出了妥协-这比抛出异常要好,并且可以按照大多数程序员的预期工作。


1
什么?我不明白,你的意思是DateTime无法解析毫秒以下的时间吗?而且MSDN的引用也没有解释为什么他们要这样实现。一个良好实现的方法的行为应该是显而易见的,而不必阅读文档的细节。 - fearofawhackplanet
2
这并没有回答问题,即为什么该函数接受 double 类型的参数却最终将其转换为整型。 - sleske
1
虽然这是有文档记录的,但它并没有回答为什么要有一个接受double的重载,而实际上只接受int。而且DateTime使用的精度比毫秒高:“时间值以称为滴答的100纳秒单位来测量”,请参见http://msdn.microsoft.com/en-us/library/system.datetime.aspx。 - Dirk Vollmar

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