Где я могу найти epsilon машины в С#?
Эпсилон машины канонически определяется как наименьшее число, добавленное к одному, дает результат, отличный от одного.
Существует Double.Epsilon
, но имя очень вводит в заблуждение: это наименьшее (денормализованное) значение Double
, представляемое и, следовательно, бесполезное для любого типа числового программирования.
Я хотел бы получить истинный epsilon для типа Double
, чтобы не иметь ограничений жесткого кода в моей программе. Как это сделать?
Ответы
Ответ 1
Это (на моей машине):
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 раза эпсилон, теперь это должно быть правильно.
Ответ 2
Библиотека Math.NET определяет Precision, который имеет свойство 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
в соответствии с этим источником.
Ответ 3
Просто скорректируйте значение:
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;
И посмотрите Википедия: машина epsilon.
Ответ 4
Ref. рутина в Meonester's:
Фактически значение machEps при выходе из цикла do... while таково, что 1 + machEps == 1.
Чтобы получить эпсилон машины, мы должны вернуться к предыдущему значению, добавив следующее после цикла:
machEps * = 2.0D;
Это вернет 2.2204460492503131e-16 в соответствии с рекомендацией в документации Microsoft для Double.Epsilon.