Я реализовывал довольно сложный численный алгоритм.
Он содержит некоторые экспоненты, среди которых я обнаружил, после печати промежуточного результата, что были некоторые переполнения 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
, принимая это за истинную бесконечность, и в конце концов разберитесь с ее результатами?
Или если нет, я должен поймать это? Но как я могу, так как это не максимальный или минимальный двойной?
Как уже упоминалось в других ответах, поведение чисел с плавающей запятой не является четко определенным стандартом, однако оно довольно хорошо определяется МЭК-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 Это не официальный ресурс, но, насколько я знаю, это правильно.
Ограничение этого ответа для 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
Есть ли инфо о c ++ …
Стандарт C ++ не устанавливает каких-либо требований к поведению бесконечности — или что бесконечность может быть представлена числами с плавающей запятой.
Если ваша система использует числа с плавающей запятой, которые соответствуют определенному стандарту с плавающей запятой, тогда этот стандарт может определять поведение бесконечностей.
Кажется, что inf действительно напоминает нашу концепцию бесконечности, но не равна максимальным и минимальным значениям std.
В самом деле. numeric_limits::max()
определяется, чтобы вернуть максимум конечный значение.
как ловить бесконечность], так как это не максимальный или минимальный дубль?
Если по ловить Вы имеете в виду, что вы хотите проверить, является ли значение бесконечностью, вы можете сравнить с numeric_limits::infinity()
или, если у вас есть C ++ 11, то std::isinf()
(который проверяет как положительную, так и отрицательную бесконечность).