Como faço para verificar se um número avalia para o infinito?

94

Eu tenho uma série de cálculos Javascript que (somente no IE) mostram o Infinity dependendo das escolhas do usuário.

Como impedir que a palavra Infinityapareça e, por exemplo, mostrar 0.0?

Homer_J
fonte

Respostas:

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

Você poderia usar a isFinitefunção em vez disso, dependendo de como deseja tratar NaN. isFiniteretorna falsese o seu número for POSITIVE_INFINITY, NEGATIVE_INFINITYou NaN.

if (isFinite(result))
{
    // ...
}
LukeH
fonte
2
Por que usar em Number.(POSITIVE|NEGATIVE)_INFINITYvez de -?Infinityou -?1/0?
Eli Gray
5
@Eli: a Infinitypropriedade global não é somente leitura, o que significa que pode ser redefinida: por exemplo, var x = 42; Infinity = 42; alert(x === Infinity);exibe "true" . (É certo que é um caso obscuro, e quem decide redefinir Infinity, NaNetc deve esperar coisas estranhas a acontecer.)
LukeH
Ignorando o fato de que Number.(POSITIVE|NEGATIVE)_INFINITYtambém não é somente leitura, Infinity é somente leitura no modo estrito. Além disso, e o -?1/0caso que apresentei a você? De qualquer forma, você quase sempre deve usar no isFinitelugar.
Eli Gray
1
@Eli: Em meus testes Number.POSITIVE_INFINITYe Number.NEGATIVE_INFINITY são somente leitura (testado no Chrome8, FF3.6 e IE8). Usar 1/0funciona bem, mas não será tão óbvio para os mantenedores do seu código o que você está tentando testar. Concordo que usar isFiniteé quase sempre a melhor maneira de fazer as coisas - é por isso que mencionei isso em minha resposta - mas apenas o OP pode decidir se atende aos seus requisitos.
LukeH
4
Eles não são somente leitura (leia-se: não configurável ), são apenas acessores com getters, mas sem setters. Você pode redefini-los com Object.definePropertye __defineGetter__. Infinity, por outro lado, não é configurável no modo estrito.
Eli Gray
9

Um simples n === n+1ou n === n/0funciona:

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

Esteja ciente de que o nativo isFinite()força a entrada de números. isFinite([])e isFinite(null)são ambos, truepor exemplo.

Ryanve
fonte
Esta resposta está completamente errada. n === n+1avalia como verdadeiro para todos os números maiores que 2 ^ 53, ou seja, 1e30. O hack da divisão funciona, mesmo para NaN e -Infinity. No entanto, a resposta de LukeH fornece um código muuuuito mais legível.
tglas
@tglas Por que o plus é assim? Ainda bem que a divisão é sólida. IMO meu código é mais legível e mais inclusivo porque a matemática é mais universal do que palavras.
Ryanve,
1
Como os floats IEEE de 64 bits têm 53 dígitos binários significativos (consulte en.wikipedia.org/wiki/IEEE_754 ), n+1não podem ser representados e estão sujeitos a arredondamento. Bem, mesmo os inteiros são afetados por erros de arredondamento. A propósito, não acho que seu código seja "à prova de matemática", apenas tente n === n/-0. Ao completar os reais com +/- inf, seu limite não é bem definido, a menos que a sequência zero subjacente seja considerada positiva.
tglas
Obrigado @tglas. Sempre adorarei que o JavaScript possa ser dividido por zero :)
ryanve
6

In ES6, O Number.isFinite()método determina se o valor passado é um número finito.

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

Number.isFinite(0);         // true
Number.isFinite(2e64);      // true
zangw
fonte
Acessível em ECMAScript 1
MohaMad
2

Na verdade, n === n + 1 funcionará para números maiores que 51 bits, por exemplo

1e16 + 1 === 1e16; // true
1e16 === Infinity; // false
Yuri
fonte
3
Este deve ser um comentário sobre a resposta de ryanve.
Gary
1

Gosto de usar Lodash por uma variedade de razões de codificação defensivas , bem como para facilitar a leitura. ES6 Number.isFiniteé ótimo e não tem problemas com valores não numéricos, mas se ES6 não for possível, você já tem lodash ou deseja um código mais breve: _.isFinite

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

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

Encontrei um cenário que exigia que eu verificasse se o valor é do tipo NaNou, Infinitymas passe as strings como resultados válidos. Como muitas strings de texto produzirão falso-positivo NaN, fiz uma solução simples para contornar isso:

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

O código acima converte valores em strings e verifica se eles são estritamente iguais a NaN ou Infinity (você precisará adicionar outro caso para infinito negativo).

Assim:

testInput(1/0); // true
testInput(parseInt("String")); // true
testInput("String"); // false
Dmitrizzle
fonte
Esta postagem realmente não lida com a questão real aqui e teria sido melhor como um comentário sob a resposta aceita. O OP é sobre números e infinito, não strings e NaNs, etc.
code_dredd
Você provavelmente está certo, @code_dredd - a anedota não é relevante. Mas a solução ainda funciona: ele pode detectar o número infinito - corrija-me se eu estiver errado.
dmitrizzle 01 de
Isso não vem ao caso. Já existe uma resposta que mostra como fazer isso corretamente . O que você tem "funciona" simplesmente porque a própria linguagem faz coisas bobas e é inconsistente com a forma como gerencia tipos. Por favor, evite escrever código de hack como este.
code_dredd 01 de
Você ficaria mais feliz se eu usasse toString()? Sinta-se à vontade para votar negativamente ou declarar motivos como isso pode gerar resultados inconsistentes ou por que exatamente esse método não é recomendado. Até agora, ainda sinto que adiciona uma opção para quem está procurando uma resposta e não há nenhuma razão concreta para que isso seja perigoso, instável, etc.
dmitrizzle
-1

Você pode usar isFinite na janela isFinite(123):

Você pode escrever uma função como:

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

E use como:

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

Você também pode Number.isFinitverificar se o valor também é Número e se é mais preciso para verificação undefinede nulletc ...

Ou você pode polyfill assim:

Number.isFinite = Number.isFinite || function(value) {
  return typeof value === 'number' && isFinite(value);
}
Alireza
fonte