c# - Math.Floor(double) 和 Math.Ceiling(double) 的意外行为

标签 c# floating-point

这个问题是关于 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离其实际值(value)。 (我后来发现内置的 Math.Log10(double) 提供了更准确的结果。)

阈值是否应该绑定(bind)到 Double.Epsilon 或者,如果不是,阈值是否应该被记录(我在官方 MSDN 文档中找不到任何提及) ?

最佳答案

Shouldn't the threshold should be tied to Double.Epsilon

没有。

可表示的 double 并不是均匀分布在实数上。接近于零,有许多可表示的值。但是你离零越远,可表示的 double 就越远。对于非常的大数,即使加 1 到 double 也不会得到新值。

因此,您要寻找的阈值取决于您的数字有多大。它不是常数。

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

相关文章:

c# - 在 WCF REST 服务中获取原始请求 url

c++ - 使用google test和google mock比较 float 组

c - 用点 eclipse 代替逗号

c - C 如何将 double 存储到已分配的 float 类型数组中?

c# - 小数的两种显示方式

c# - Uri规范化压缩FTP方案

c# - .NET:为什么嵌套类具有在外部类中声明的泛型?

c# - 如何确定存储过程结果的列是否可以为空

python - 使用 "safe"将 float64 转换为 int64

c++ - 内存中的浮点表示对我来说不清楚