2016-12-15 27 views
1

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

Я провел тест: (г ++ версии: "Apple LLVM версии 8.0.0 (лязг-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 похоже на нашу концепцию бесконечности, но не равную max и min std.

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

+0

«общего бесконечности бы бессмысленно», я нахожу, что это трудно сдержать свой смех прямо сейчас: D – George

+0

хорошо я не родной английский пользователь QQ – Aminopterin

+0

^^ это не английский, просто утверждение, что существует бы бессмысленно бесконечность. – George

ответ

2

Как уже упоминалось в других ответах, поведение чисел с плавающей запятой не определено стандартом, однако оно довольно хорошо определено IEC-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#operations , например -inf * -inf = +inf, +inf + +inf = +Inf и т. Д. Стандартные математические функции также имеют четкое поведение с бесконечностью, поэтому вы также можете положиться на них.

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


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

+0

Упрощенный для кармы (и тот факт, что этот ответ действительно довольно хорош). Я отменил один из ваших комментариев, которые вы сделали, и поместите его в мой ответ. – Bathsheba

+0

Да, у меня есть 'is_iec559' true. Хорошие новости. (Извините, что только сейчас у меня есть время проверить это.) – Aminopterin

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

+0

'std :: log (0.0)' должен, вероятно, возвращать '-Inf';) – Holt

+0

Могу поклясться, что это должен вернуться + Inf: выкопает стандарт позже. Математически log (0) является одним из худших полюсов, с которыми вы можете столкнуться. – Bathsheba

+0

Я проверил, это действительно 'inf'. Почему это худший полюс? Это потому, что log (0) не может быть расширен Laurent? (Я полагаю, нет, но не знаю, как показать.) --- отступление, в любом случае, помилование. – Aminopterin

1

Существует ли в C++ СТАНДА инфа ...

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

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

Похоже, что inf напоминает нашу концепцию бесконечности, но не равную max и min std.

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

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

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

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

  • Нет связанных вопросов^_^