【发布时间】:2012-03-28 22:50:24
【问题描述】:
这个问题是关于Math.Floor(double) 和Math.Ceiling(double) 决定给你上一个或下一个整数值的阈值。心烦意乱地发现阈值似乎与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 官方文档中找不到任何提及)?
【问题讨论】:
-
这可能与以 IEEE 形式存储此类数字的能力有关。我想知道 3.0 和 3.0 的比较 - Double.Epsilon 会得到什么。
-
@Rich:他们应该比较相等。
-
这并不奇怪,3.0 也比 0.0 大得多。它们可能看起来只有 3 之差,但这是可表示的正数的一半以上(其中一半在 0 和 1 之间)的差异。
标签: c# floating-point