переполнение — ведет ли inf c ++ к стандартному поведению точно так же, как бессмысленная бесконечность

Я реализовывал довольно сложный численный алгоритм.
Он содержит некоторые экспоненты, среди которых я обнаружил, после печати промежуточного результата, что были некоторые переполнения double.
Тем не менее, терминал печатает inf (не Inf или же NaN), и кажется, что это не двойной, даже не минимальный или максимальный выражаемый двойной.
Но похоже inf ведет себя так, как если бы это была расширенная система вещественных чисел (точка зрения, что положительная и отрицательная бесконечность должны рассматриваться как истинное число, а не как аббревиатура с ограничениями).

Я провел тест: (версия g ++: «Apple LLVM версия 8.0.0 (clang-800.0.42.1)»)

#include <iostream> // cout
#include <cmath> // exp, log
#include <limits> // data ranges

int main(void)
{
const double dMin =std::numeric_limits<int>::min();
const double dMax =std::numeric_limits<int>::max();
double p1 =std::exp(710);
double p2 =std::exp(750);
double p3 =std::exp(800);
double p4 =-std::log(0.0);
std::cout << "p1 :=std::exp(710) =" << p1 << '\n';
std::cout << "p2 :=std::exp(750) =" << p2 << '\n';
std::cout << "p3 :=std::exp(800) =" << p3 << '\n';
std::cout << "p4 :=-std::log(0.0) =" << p4 << '\n';
std::cout << "does p1==dMax? " << ( (p1==dMax) ? "yes" : "no" ) << '\n';
std::cout << "does p1==-dMin? " << ( (p1==-dMin) ? "yes" : "no" ) << '\n';
std::cout << "does p1==p2? " << ( (p1==p2) ? "yes" : "no" ) << '\n';
std::cout << "does p2==p3? " << ( (p2==p3) ? "yes" : "no" ) << '\n';
std::cout << "does p3==p4? " << ( (p3==p4) ? "yes" : "no" ) << '\n';
std::cout << "does 3*p1==p2/2+1? " << ( (3*p1==p2/2+1) ? "yes" : "no" ) << '\n';
std::cout << "does (-p1)*(-p2)==p3*p3*p3? " << ( ((-p1)*(-p2)==p3*p3*p3) ? "yes" : "no" ) << '\n';
std::cout << "does std::log(p2)==std::exp(p3)? " << ( (std::log(p2)==std::exp(p3)) ? "yes" : "no" ) << '\n';
}

Выход:

p1 :=std::exp(710) =inf
p2 :=std::exp(750) =inf
p3 :=std::exp(800) =inf
p4 :=-std::log(0.0) =inf
does p1==dMax? no
does p1==-dMin? no
does p1==p2? yes
does p2==p3? yes
does p3==p4? yes
does 3*p1==p2/2+1? yes
does (-p1)*(-p2)==p3*p3*p3? yes
does std::log(p2)==std::exp(p3)? yes

Кажется, что inf действительно напоминает нашу концепцию бесконечности, но не равно максимальному и минимальному стандарту.

Можно ли предположить, что inf работает так же, как бессмысленная бесконечность?
Могу ли я положиться на операции на промежуточных этапах моего алгоритма, который включает в себя inf, принимая это за истинную бесконечность, и в конце концов разберитесь с ее результатами?
Или если нет, я должен поймать это? Но как я могу, так как это не максимальный или минимальный двойной?

1

Решение

Как уже упоминалось в других ответах, поведение чисел с плавающей запятой не является четко определенным стандартом, однако оно довольно хорошо определяется МЭК-559 / IEEE-754, и большинство реализаций используют это. Первое, что нужно сделать, это проверить, эффективно ли это использует ваша реализация:

static_assert(std::numeric_limits<double>::is_iec559, "Stupid implementation!");

Как только вы подтвердите это утверждение, все станет намного проще! Во-первых, вы можете использовать следующую служебную функцию, чтобы получить правда бесконечность (вам не нужно is_iec559 чтобы быть правдой, чтобы это работало на самом деле …)

std::numeric_limits<double>::infinity()

Более того, IEEE-754 имеет очень четко определенные правила поведения бесконечности:
http://steve.hollasch.net/cgindex/coding/ieeefloat.html#operations1, например -inf * -inf = +inf, +inf + +inf = +Inf, и так далее. Стандартные математические функции также имеют четко определенное поведение с бесконечностью, поэтому вы также можете на них положиться.

Так что, если ваша реализация соответствует стандарту IEEE, да Вы можете рассчитывать на промежуточные операции на бесконечности и проверять только конечные результаты.


1 Это не официальный ресурс, но, насколько я знаю, это правильно.

2

Другие решения

Ограничение этого ответа для IEEE754 с плавающей запятой, + Inf возникает в результате вычислений, подобных 1.0 / 0.0и -Inf возникает из чего-то вроде -1.0 / 0.0,

Другой тип, NaN (не число) возникает из 0.0 / 0.0,

Две переменные с плавающей точкой установлены в +Inf будет сравнивать true друг с другом, то же самое -Inf, Они представляют разные величины для std::numeric_limits<double>::max(), +Inf больше, чем все значения, кроме себя и NaN,

Обратите внимание, что две переменные с плавающей точкой установлены в NaN будут не сравнить true друг с другом, или с чем-либо еще в этом отношении.

(Для чего это стоит, std::log(0.0) должен вернуть -Inf, скорее, чем NaN). Увидеть http://en.cppreference.com/w/cpp/numeric/math/log

2

Есть ли инфо о c ++

Стандарт C ++ не устанавливает каких-либо требований к поведению бесконечности — или что бесконечность может быть представлена ​​числами с плавающей запятой.

Если ваша система использует числа с плавающей запятой, которые соответствуют определенному стандарту с плавающей запятой, тогда этот стандарт может определять поведение бесконечностей.

Кажется, что inf действительно напоминает нашу концепцию бесконечности, но не равна максимальным и минимальным значениям std.

В самом деле. numeric_limits::max() определяется, чтобы вернуть максимум конечный значение.

как ловить бесконечность], так как это не максимальный или минимальный дубль?

Если по ловить Вы имеете в виду, что вы хотите проверить, является ли значение бесконечностью, вы можете сравнить с numeric_limits::infinity()или, если у вас есть C ++ 11, то std::isinf() (который проверяет как положительную, так и отрицательную бесконечность).

1
По вопросам рекламы [email protected]