机器epsilon通常定义为加一后与一不同的最小数字。
虽然有Double.Epsilon
,但名称非常误导:它是可表示的最小(非规范化)Double
值,因此对于任何类型的数值编程都没有用。
我想获取Double
类型的真正epsilon,以便不必在程序中硬编码公差。我该怎么做?
机器epsilon通常定义为加一后与一不同的最小数字。
虽然有Double.Epsilon
,但名称非常误导:它是可表示的最小(非规范化)Double
值,因此对于任何类型的数值编程都没有用。
我想获取Double
类型的真正epsilon,以便不必在程序中硬编码公差。我该怎么做?
在我的机器上:
1.11022302462516E-16
double machEps = 1.0d;
do {
machEps /= 2.0d;
}
while ((double)(1.0 + machEps) != 1.0);
Console.WriteLine( "Calculated machine epsilon: " + machEps );
已修改:
我计算了 2 倍的 epsilon,现在应该正确了。
Math.NET
代码所示的相符。 - Christian.K(1.0 + machEps) == 1.0
,这不是我们想要的。我们想要最后一个值,使得(1.0 + machEps) != 1.0
。 - RupMath.NET库定义了一个Precision类,其中有一个DoubleMachineEpsilon属性。
您可以查看它们的实现方式。
根据它的解释,DoubleMachineEpsilon是:
/// <summary>
/// The base number for binary values
/// </summary>
private const int BinaryBaseNumber = 2;
/// <summary>
/// The number of binary digits used to represent the binary number for a double precision floating
/// point value. i.e. there are this many digits used to represent the
/// actual number, where in a number as: 0.134556 * 10^5 the digits are 0.134556 and the exponent is 5.
/// </summary>
private const int DoublePrecision = 53;
private static readonly double doubleMachinePrecision = Math.Pow(BinaryBaseNumber, -DoublePrecision);
根据这个来源,它是1,11022302462516E-16
。
System.Double
的内部表示方式,而我还没有准备好去处理它(这不仅仅是 IEEE754 的问题,还涉及字节序等问题)。 - Alexandre C.Double.Epsilon
的文档页面上都没有提到“机器epsilon”,这才是你想要的正确术语,所以我不确定它是否令人困惑。 - Rupdouble.Epsilon
和机器epsilon不同这个事实,与Microsoft的FP实现是否正确完全无关。 - LukeH直接硬编码数值:
const double e1 = 2.2204460492503131e-16;
或者使用二的幂次方:
static readonly double e2 = Math.Pow(2, -52);
static readonly double e3 = BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(1.0) + 1L) - 1.0;
请查看维基百科:机器精度了解更多信息。
LAPACK + DLAMCH,64位英特尔处理器,C#:
var pp = double.Epsilon; // pp = 4.94065645841247E-324
double p = NativeMethods.MachinePrecision('S'); // =DLAMCH('S')
p = 2.2250738585072014E-308
double.MinValue = -1.7976931348623157E+308
double.MaxValue = 1.7976931348623157E+308
关于Meonester的程序: 实际上,在do ... while循环结束时,machEps的值是这样的:1+machEps == 1。 要获取机器精度,我们必须回到先前的值,在循环后添加以下内容: machEps *= 2.0D; 这将返回2.2204460492503131e-16,与Microsoft文档中Double.Epsilon的建议一致。
Double.MinValue
很可能是定义为与 .NET Framework 中的其他MinValue
字段相对应,例如Int32.MinValue
、DateTime.MinValue
等。这显然与 C 中的DBL_MIN
不同。但是,我同意Double.Epsilon
的定义令人困惑。 - Martin Liversage