2016-12-15 1 views
1

Je mettais en œuvre un algorithme numérique raisonnablement compliqué. Il contient quelques exponentielles, parmi lesquelles j'ai découvert, lors de l'impression du résultat intermédiaire, qu'il y avait des débordements de double. Cependant, le terminal imprime inf (pas Inf ou NaN), et il semble que ce ne soit pas un double, pas même le double minimum ou maximum exprimable. Mais il semble que inf se comporte comme s'il s'agissait du système de nombres réels étendus (la perspective que l'infini positif et négatif soit considéré comme un vrai nombre, plutôt qu'une abréviation de déclaration impliquant des limites).Est-ce que C++ std's inf se comporte exactement comme un infini commun-sensuel

J'ai effectué un test: (g ++ version: "la version d'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'; 
} 

Sortie:

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 

Il semble que inf ressemble à notre concept de l'infini, mais n'est pas égal à max et min de std.

Est-il sûr, alors, de supposer que inf fonctionne de la même manière que l'infini sens commun? Puis-je compter sur les opérations dans les étapes intermédiaires de mon algorithme qui implique inf, en prenant pour être l'infini vrai, et ne traitent que ses résultats à la fin? Ou sinon, devrais-je l'attraper? Mais comment puis-je, puisque ce n'est pas le double maximum ou minimum?

+0

« l'infini tombe sous le sens », je trouve qu'il est difficile de contenir mon rire en ce moment: D – George

+0

bien que je ne suis pas natif utilisateur anglais QQ – Aminopterin

+0

^^ ce ne sont pas les Anglais, juste l'affirmation qu'il existe un sensical infini. – George

Répondre

2

Comme déjà mentionné par les autres réponses, le comportement des nombres à virgule flottante n'est pas bien défini par le standard, cependant il est assez bien défini par IEC-559/IEEE-754, et la plupart des implémentations l'utilisent. La première chose à faire serait de vérifier si votre application utilise efficacement:

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

Une fois que vous avez passé cette affirmation, les choses deviennent beaucoup plus facile! Tout d'abord, vous pouvez utiliser la fonction d'utilité suivante pour obtenir un vrai infini (vous n'avez pas besoin is_iec559 être vrai pour que cela fonctionne en fait ...):

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

Mieux, IEEE-754 a très bien - règles définies pour le comportement de l'infini: http://steve.hollasch.net/cgindex/coding/ieeefloat.html#operations , par exemple -inf * -inf = +inf, +inf + +inf = +Inf, et ainsi de suite. Les fonctions mathématiques standard ont également un comportement bien défini avec l'infini, vous pouvez donc vous y fier aussi.

Donc si votre implémentation suit la norme IEEE, oui vous pouvez vous fier aux opérations intermédiaires sur infinity et ne vérifier que les résultats finaux.


Ce n'est pas une ressource officielle mais pour autant que je sache, il est correct.

+0

Refusé pour le karma (et le fait que cette réponse soit vraiment plutôt bonne) - J'ai entaillé un de vos commentaires et je l'ai mis dans ma réponse. – Bathsheba

+0

Oui, le mien a 'is_iec559' vrai. Bonnes nouvelles. (Excusez-moi que seulement maintenant j'ai le temps de vérifier cela.) – Aminopterin

2

En restreignant cette réponse au point flottant IEEE754, + Inf provient d'un calcul comme 1.0/0.0, et -Inf provient de quelque chose comme -1.0/0.0.

Un autre type, NaN (pas un nombre) provient de 0.0/0.0.

Deux variables à virgule flottante mis à +Inf comparera true les uns avec les autres, idem -Inf. Ils représentent des quantités différentes à std::numeric_limits<double>::max(). +Inf est supérieure à toutes les valeurs sauf elle-même et NaN.

Notez que deux variables à virgule flottante mis à NaN ne pas comparer true entre eux, ou avec toute autre chose pour cette question.

(Pour ce que ça vaut, std::log(0.0)doit retour -Inf, plutôt que NaN). Voir http://en.cppreference.com/w/cpp/numeric/math/log

+0

'std :: log (0.0)' devrait probablement retourner '-Inf';) – Holt

+0

Je pourrais jurer qu'il doit retourner + Inf: va déterrer la norme plus tard. Mathématiquement log (0) est l'un des pires pôles que vous pouvez rencontrer. – Bathsheba

+0

J'ai vérifié, c'est vraiment «inf». Pourquoi est-ce le pire des pôles? Est-ce parce que log (0) ne peut pas être étendu à Laurent? (Je suppose que non, mais je ne sais pas comment montrer.) --- digression de toute façon, pardon. – Aminopterin

1

Est-ce que C++ std de ... inf

La norme C++ ne spécifie pas de conditions pour la façon dont se comporte l'infini - ou que l'infini peut être représenté par des nombres à virgule flottante.

Si votre système utilise des nombres à virgule flottante conformes à une norme à virgule flottante particulière, cette norme peut spécifier le comportement des infinis.

Il semble que inf ressemble à notre concept de l'infini, mais pas égal à max et min de std.

En effet. numeric_limits::max() est défini pour renvoyer le maximum valeur finie.

comment [à capture infini], car il est pas le maximum ou double minimum?

Si par prise vous voulez dire que vous souhaitez vérifier si une valeur est infini, vous pouvez comparer à numeric_limits::infinity(), ou si vous avez C++ 11, puis std::isinf() (qui vérifie l'infini à la fois positives et négatives).