这个问题是关于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绑定(bind),否则,不应记录该阈值(我在MSDN官方文档中找不到对此的任何提及)?

最佳答案



不。

可表示的 double 并非均匀分布在实数上。接近零,有许多可表示的值。但是,离零越远,可代表的 double 值就越远。对于非常大的数字,即使将1加到 double 值也不会给您带来新的值(value)。

因此,您要寻找的阈值取决于您的人数。这不是一个常数。

关于c# - Math.Floor(double)和Math.Ceiling(double)的异常行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9916808/

10-12 12:43
查看更多