这个问题涉及到Math.Floor(double)
和Math.Ceiling(double)
决定给出上一个或下一个整数值的阈值。我很惊讶地发现,这个阈值似乎与Double.Epsilon
无关,而Double.Epsilon
是可以用double表示的最小值。例如:
double x = 3.0;
Console.WriteLine( Math.Floor( x - Double.Epsilon ) ); // expected 2, got 3
Console.WriteLine( Math.Ceiling( x + Double.Epsilon) ); // expected 4, got 3
即使将Double.Epsilon
乘以相当大的数也无法实现:
Console.WriteLine( Math.Floor( x - Double.Epsilon*1000 ) ); // expected 2, got 3
Console.WriteLine( Math.Ceiling( x + Double.Epsilon*1000) ); // expected 4, got 3
通过一些试验,我能够确定这个阈值大约在2.2E-16左右,虽然很小,但是比Double.Epsilon
要大得多。这个问题的原因是,我试图使用公式
var digits=Math.Floor(Math.Log(n,10))+1
计算一个数字的位数。但是这个公式对于n=1000
并不适用,因为Math.Log(1000,10)
返回的数字与其实际值相差4.44E-16(这完全是意外发现的)。后来我发现内置的Math.Log10(double)
提供了更准确的结果。这个阈值是否应该与
Double.Epsilon
相关联呢?如果不是的话,难道这个阈值就不应该被记录下来吗?(我在官方MSDN文档中找不到任何提及此事的内容)