Comment vérifier si un nombre est évalué à l'infini?


94

J'ai une série de calculs Javascript qui (uniquement sous IE) montrent Infinity en fonction des choix de l'utilisateur.

Comment empêcher le mot d' Infinityapparaître et, par exemple, montrer à la 0.0place?

Réponses:


174
if (result == Number.POSITIVE_INFINITY || result == Number.NEGATIVE_INFINITY)
{
    // ...
}

Vous pouvez éventuellement utiliser la isFinitefonction à la place, selon la façon dont vous souhaitez traiter NaN. isFiniteretourne falsesi votre numéro est POSITIVE_INFINITY, NEGATIVE_INFINITYou NaN.

if (isFinite(result))
{
    // ...
}

2
Pourquoi utiliser à la Number.(POSITIVE|NEGATIVE)_INFINITYplace de -?Infinityou -?1/0?
Eli Gray

5
@Eli: La Infinitypropriété globale n'est pas en lecture seule, ce qui signifie qu'elle peut être redéfinie: par exemple, var x = 42; Infinity = 42; alert(x === Infinity);affiche "true" . (Certes, c'est un cas obscur, et quiconque décide de redéfinir Infinity, NaNetc. devrait s'attendre à ce que des choses étranges se produisent.)
LukeH

Ignorer le fait que ce Number.(POSITIVE|NEGATIVE)_INFINITYn'est pas non plus en lecture seule, Infinity est en lecture seule en mode strict. Et qu'en est-il du -?1/0cas que je vous ai présenté? Quoi qu'il en soit, vous devriez presque toujours utiliser à la isFiniteplace.
Eli Gray

1
@Eli: Dans mes tests Number.POSITIVE_INFINITYet Number.NEGATIVE_INFINITY sont en lecture seule (testés sur Chrome8, FF3.6 et IE8). L'utilisation 1/0fonctionne bien, mais ce ne sera pas si évident pour les responsables de votre code ce que vous essayez réellement de tester. Je conviens que l'utilisation isFiniteest presque toujours la meilleure façon de faire les choses - c'est pourquoi je l'ai mentionné dans ma réponse - mais seul le PO peut décider si cela répond à leurs exigences.
LukeH

4
Ils ne sont pas en lecture seule (lire: non configurables ), ce ne sont que des accesseurs avec des getters mais pas des setters. Vous pouvez les redéfinir avec Object.definePropertyet __defineGetter__. Infinity, d'autre part, n'est pas configurable en mode strict.
Eli Gray

9

Un simple n === n+1ou n === n/0fonctionne:

function isInfinite(n) {
  return n === n/0;
}

Sachez que le natif isFinite()contraint les entrées aux nombres. isFinite([])et isFinite(null)sont les deux truepar exemple.


Cette réponse est tout simplement fausse. n === n+1vaut vrai pour tous les nombres supérieurs à 2 ^ 53, c'est-à-dire 1e30. Le hack de division fonctionne, même pour NaN et -Infinity. Cependant, la réponse de LukeH vous donne un code plus lisible.
tglas

@tglas Pourquoi le plus comme ça? Heureux que la division soit solide. IMO mon code est plus lisible et plus inclusif car les mathématiques sont plus universelles que les mots.
ryanve le

1
Étant donné que les flottants IEEE 64 bits ont 53 chiffres binaires significatifs (voir en.wikipedia.org/wiki/IEEE_754 ), ils n+1ne peuvent donc pas être représentés et sont sujets à des arrondis. Eh bien, même les entiers sont affectés par les erreurs d'arrondi. Btw, je ne pense pas que votre code soit "math-proof", essayez juste n === n/-0. Lorsque vous complétez les réels avec +/- inf, votre limite n'est pas bien définie à moins que la séquence zéro sous-jacente ne soit supposée positive.
tglas

Merci @tglas, j'aimerai toujours que JavaScript puisse diviser par zéro :)
ryanve

6

In ES6, La Number.isFinite()méthode détermine si la valeur transmise est un nombre fini.

Number.isFinite(Infinity);  // false
Number.isFinite(NaN);       // false
Number.isFinite(-Infinity); // false

Number.isFinite(0);         // true
Number.isFinite(2e64);      // true

Accessible de ECMAScript 1
MohaMad

2

En fait, n === n + 1 fonctionnera pour les nombres supérieurs à 51 bits, par exemple

1e16 + 1 === 1e16; // true
1e16 === Infinity; // false

3
Cela devrait être un commentaire sur la réponse de Ryanve.
Gary

1

J'aime utiliser Lodash pour diverses raisons de codage défensif ainsi que pour la lisibilité. ES6 Number.isFiniteest génial et n'a pas de problèmes avec les valeurs non numériques, mais si ES6 n'est pas possible, vous avez déjà lodash ou voulez un code plus court : _.isFinite

_.isFinite(Infinity); // false
_.isFinite(NaN); // false
_.isFinite(-Infinity); // false

_.isFinite(null); // false
_.isFinite(3); // true
_.isFinite('3'); // true

0

J'ai rencontré un scénario qui m'obligeait à vérifier si la valeur est du type NaNou Infinitymais à passer des chaînes comme résultats valides. Étant donné que de nombreuses chaînes de texte produiront des faux positifs NaN, j'ai proposé une solution simple pour contourner cela:

  const testInput = input => input + "" === "NaN" || input + "" === "Infinity";

Le code ci-dessus convertit les valeurs en chaînes et vérifie si elles sont strictement égales à NaN ou Infinity (vous devrez ajouter un autre cas pour l'infini négatif).

Alors:

testInput(1/0); // true
testInput(parseInt("String")); // true
testInput("String"); // false

Cet article ne traite pas vraiment de la question réelle ici et aurait été mieux comme commentaire sous la réponse acceptée. L'OP concerne les nombres et l'infini, pas les chaînes et les NaNs, etc.
code_dredd

Vous avez probablement raison, @code_dredd - l'anecdote n'est pas pertinente. Mais la solution fonctionne toujours: elle peut détecter le nombre infini - veuillez me corriger si je me trompe.
dmitrizzle

C'est hors de propos. Il existe déjà une réponse qui montre comment faire cela correctement . Ce que vous avez "fonctionne" simplement parce que le langage lui-même fait des choses stupides et est incompatible avec la façon dont il gère les types. Veuillez vous éviter d'écrire du code de piratage comme celui-ci.
code_dredd

Cela vous rendrait-il plus heureux si j'utilisais à la toString()place? N'hésitez pas à voter contre ou à indiquer les raisons pour lesquelles cela pourrait donner des résultats incohérents ou pourquoi exactement cette méthode n'est pas recommandée. Jusqu'à présent, je pense toujours que cela ajoute une option pour quiconque cherche une réponse et il n'y a pas de raisons concrètes pour lesquelles c'est dangereux, instable, etc.
dmitrizzle

-1

Vous pouvez utiliser isFinite dans la fenêtre, isFinite(123):

Vous pouvez écrire une fonction comme:

function isInfinite(num) {
 return !isFinite(num);
}

Et utilisez comme:

isInfinite(null); //false
isInfinite(1); //false
isInfinite(0); //false
isInfinite(0.00); //false
isInfinite(NaN); //true
isInfinite(-1.797693134862316E+308); //true
isInfinite(Infinity); //true
isInfinite(-Infinity); //true
isInfinite(+Infinity); //true
isInfinite(undefined); //true

Vous pouvez également Number.isFinitvérifier si la valeur est également Number et est plus précise pour la vérification undefined, nulletc.

Ou vous pouvez le polyfill comme ceci:

Number.isFinite = Number.isFinite || function(value) {
  return typeof value === 'number' && isFinite(value);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.