Подтвердить что ты не робот

Как (переносимо) получить DBL_EPSILON в C и С++

Я использую GCC 3.4 для Linux (AS 3) и пытаюсь найти, чтобы получить DBL_EPSILON или, по крайней мере, приличное приближение. Как я могу получить это программно?

4b9b3361

Ответ 1

Он должен быть в "float.h". Это переносимо, это часть стандартов C и С++ (хотя и устарела на С++ - используйте <cfloat> или sbi ответ для "гарантированной" передовой совместимости).

Если у вас его нет, то, поскольку ваши парные разряды являются 64-битными IEEE, вы можете просто украсть это значение у кого-то другого float.h. Вот первый, который я нашел:

http://opensource.apple.com/source/gcc/gcc-937.2/float.h

#define DBL_EPSILON 2.2204460492503131e-16

Значение выглядит правильно для меня, но если вы хотите быть уверенным в своем компиляторе, вы можете проверить, что (1.0 + DBL_EPSILON) != 1.0 && (1.0 + DBL_EPSILON/2) == 1.0

Изменить: я не совсем уверен, что вы подразумеваете под "программным способом". Это стандартная константа, вы не должны ее вычислять, это свойство реализации, данное вам в файле заголовка. Но я думаю, вы могли бы сделать что-то подобное. Опять же, если предположить, что представление IEEE или что-то в этом роде, так что DBL_EPSILON должен быть любой мощностью 0,5, представляет собой 1 в последнем бите точности представления 1.0:

double getDblEpsilon(void) {
    double d = 1;
    while (1.0 + d/2 != 1.0) {
        d = d/2;
    }
    return d;
}

Остерегайтесь того, что в зависимости от настроек компилятора промежуточные результаты могут иметь более высокую точность, чем double, и в этом случае вы получите меньший результат для d, чем DBL_EPSILON. Проверьте свое руководство по компиляции или найдите способ, чтобы значение 1.0 + d/2 было сохранено и перезагружено до фактического объекта double, прежде чем сравнивать его с 1.0. Очень грубо говоря, на ПК это зависит от того, использует ли ваш компилятор инструкции x86 FPU (более высокая точность) или новые операторы с плавающей запятой x64 (двойная точность).

Ответ 2

В С++ он std::numeric_limits<double>::epsilon().