2012-02-22 1 views
11

Машина epsilon канонически определяется как наименьшее число, которое добавляется к одному, дает результат, отличный от одного.Где я могу найти epsilon машины в C#?

Существует Double.Epsilon, но это имя вводит в заблуждение: это наименьшее (денормализованное) значение, представляемое и, следовательно, бесполезное для любого числового программирования.

Я хотел бы получить true epsilon для типа Double, так что не нужно иметь жесткие ограничения в моей программе. Как мне это сделать ?

+0

Релевантно: http://www.johndcook.com/blog/2010/06/08/c-math-gotchas/ – AakashM

+0

@AakashM: Я читал это. Смысл epsilon довольно ясен с точки зрения IEEE754, и стыдно, что Microsoft сделала что-то такое дилетантское. Реализуется ли их реализация с плавающей точкой? –

+0

@AlexandreC .: 'Double.MinValue', скорее всего, определяется так, как он должен соответствовать другим полям« MinValue »в .NET Framework, например« Int32.MinValue »,' DateTime.MinValue' и т. Д. Это, очевидно, не то же, что и 'DBL_MIN' на C. Однако я согласен с тем, что определение' Double.Epsilon' запутывает. –

ответ

8

Это (на моей машине):

1.11022302462516E-16 

Вы можете легко вычислить его:

 double machEps = 1.0d; 

     do { 
      machEps /= 2.0d; 
     } 
     while ((double)(1.0 + machEps) != 1.0); 

     Console.WriteLine("Calculated machine epsilon: " + machEps); 

Отредактировано:

I calcualted 2 раза эпсилон, теперь он должен быть правильным.

+0

Очень хорошая идея. Благодарю. –

+0

@Meonester Вы хотите разделить machEps на 4 каждый раз (один раз в теле и один раз в состоянии? Если я не разделяю условие (т.е. while ((double) (1.0 + (machEps))! = 1.0);) Я получаю значение для machEps 1.11022302462516E-16. – AlanT

+0

@AlanT Right, что соответствует тому, что предлагает код 'Math.NET'. –

7

В библиотеке 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 согласно этому источнику.

+0

Это довольно сложная игра, требующая многого узнать о внутреннем представлении 'System.Двойной', что я готов заняться (это не просто * IEEE754, но и проблемы с контентом и т. Д.). –

+0

@Alexandre: Я уверен, что внутреннее двоичное представление задано самим IEEE-754. Существует хорошее описание внутренних элементов 'double' [здесь] (http://csharpindepth.com/Articles/General/FloatingPoint.aspx). Также есть ссылка на класс Jon's [DoubleConverter.cs] (http://pobox.com/~skeet/csharp/DoubleConverter.cs); глядя на это, можно предложить некоторые подсказки. – LukeH

+0

@ LukeH: Теперь, когда я замечаю, что Microsoft не может получить даже самую основную терминологию, я не могу предположить, что их реализация с плавающей точкой верна для всех целей. –

0

Просто жестко закодировать значение:

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; 

И см. Wikipedia: machine epsilon.

-2

Реф. процедура в Meonester's: Фактически значение machEps при выходе из цикла do ... while равно 1 + machEps == 1. Чтобы получить эпсилон машины, мы должны вернуться к предыдущему значению, добавив следующее после цикла: machEps * = 2.0D; Это вернет 2.2204460492503131e-16 в соответствии с рекомендацией в документации Microsoft для Double.Epsilon.

Смежные вопросы