Come posso verificare se un numero restituisce infinito?


94

Ho una serie di calcoli Javascript che (solo in IE) mostrano Infinity a seconda delle scelte dell'utente.

Come si fa a impedire che la parola Infinityappaia e, ad esempio, a mostrarla 0.0?

Risposte:


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

Puoi eventualmente usare la isFinitefunzione, a seconda di come vuoi trattare NaN. isFiniterestituisce falsese il tuo numero è POSITIVE_INFINITY, NEGATIVE_INFINITYo NaN.

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

2
Perché usare al Number.(POSITIVE|NEGATIVE)_INFINITYposto di -?Infinityo -?1/0?
Eli Gray,

5
@Eli: la Infinityproprietà globale non è di sola lettura, il che significa che può essere ridefinita: ad esempio, var x = 42; Infinity = 42; alert(x === Infinity);visualizza "true" . (Certo, questo è un caso oscuro, e chiunque decida di ridefinire Infinity, NaNecc. Dovrebbe aspettarsi che accadano cose strane.)
Luca

Ignorando il fatto che Number.(POSITIVE|NEGATIVE)_INFINITYnon è nemmeno di sola lettura , Infinity è di sola lettura in modalità rigorosa. Inoltre, che mi dici del -?1/0caso che ti ho presentato? Ad ogni modo, dovresti quasi sempre usare isFiniteinvece.
Eli Gray,

1
@Eli: nei miei test Number.POSITIVE_INFINITYe Number.NEGATIVE_INFINITY sono di sola lettura (testati su Chrome8, FF3.6 e IE8). L'uso 1/0funziona bene ma non sarà così ovvio per i manutentori del tuo codice cosa stai effettivamente cercando di testare. Sono d'accordo che l'uso isFiniteè quasi sempre il modo migliore per fare le cose - ecco perché l'ho menzionato nella mia risposta - ma solo l'OP può decidere se soddisfa i loro requisiti.
LukeH

4
Non sono di sola lettura (leggi: non configurabili ), sono solo funzioni di accesso con getter ma non setter. Puoi ridefinirli con Object.definePropertye __defineGetter__. Infinity, d'altra parte, non è configurabile in modalità rigorosa.
Eli Gray

9

Un semplice n === n+1o n === n/0funziona:

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

Sii consapevole del fatto che il nativo isFinite()costringe gli input ai numeri. isFinite([])e isFinite(null)sono entrambi trueper esempio.


Questa risposta è chiaramente sbagliata. n === n+1restituisce true per tutti i numeri maggiori di 2 ^ 53, ovvero 1e30. L'hack della divisione funziona, anche per NaN e -Infinity. Tuttavia, la risposta di LukeH ti dà un codice mooolto più leggibile.
tglas

@tglas Perché il plus è così? Sono contento che la divisione sia solida. IMO il mio codice è più leggibile e più inclusivo perché la matematica è più universale delle parole.
ryanve

1
Poiché i float IEEE a 64 bit hanno 53 cifre binarie significative (vedere en.wikipedia.org/wiki/IEEE_754 ), n+1non possono essere rappresentati ed è soggetto ad arrotondamento. Ebbene, anche i numeri interi sono influenzati da errori di arrotondamento. A proposito, non penso che il tuo codice sia "a prova di matematica", prova e basta n === n/-0. Quando si completano i reali con +/- inf, il limite non è ben definito a meno che non si presuma che la sequenza zero sottostante sia positiva.
tglas

Grazie @tglas Amerò sempre il fatto che JavaScript possa dividere per zero :)
ryanve

6

In ES6, Il Number.isFinite()metodo determina se il valore passato è un numero finito.

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

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

Accessibile da ECMAScript 1
MohaMad

2

In realtà n === n + 1 funzionerà per numeri maggiori di 51 bit, es

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

3
Questo dovrebbe essere un commento alla risposta di Ryan.
Gary

1

Mi piace usare Lodash per una serie di motivi difensivi di codifica e leggibilità. ES6 Number.isFiniteè ottimo e non ha problemi con valori non numerici, ma se ES6 non è possibile, hai già lodash o desideri un codice più breve: _.isFinite

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

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

0

Mi sono imbattuto in uno scenario che mi richiedeva di verificare se il valore è del tipo NaNo Infinityma passa le stringhe come risultati validi. Poiché molte stringhe di testo producono falsi positivi NaN, ho creato una soluzione semplice per aggirarlo:

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

Il codice sopra converte i valori in stringhe e controlla se sono strettamente uguali a NaN o Infinity (dovrai aggiungere un altro caso per infinito negativo).

Così:

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

Questo post non tratta davvero la domanda reale qui e sarebbe stato meglio come commento sotto la risposta accettata. L'OP riguarda numeri e infinito, non stringhe NaNes, ecc.
code_dredd

Probabilmente hai ragione, @code_dredd: l'aneddoto non è rilevante. Ma la soluzione funziona ancora: può rilevare il numero infinito - per favore correggimi se sbaglio.
dmitrizzle

Non è questo il punto. C'è già una risposta che mostra come farlo correttamente . Quello che hai "funziona" semplicemente perché il linguaggio stesso fa cose stupide ed è incoerente con il modo in cui gestisce i tipi. Evita di scrivere codice hacker come questo.
code_dredd

Ti renderebbe più felice se lo usassi toString()invece? Sentiti libero di esprimere un voto negativo o spiegare perché questo potrebbe produrre risultati incoerenti o perché esattamente questo metodo non è raccomandato. Finora, sento ancora che aggiunge un'opzione per chiunque stia cercando una risposta e non ci sono ragioni concrete per cui questo sia pericoloso, instabile, ecc.
dmitrizzle

-1

Puoi usare isFinite nella finestra isFinite(123):

Puoi scrivere una funzione come:

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

E usa come:

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

Puoi Number.isFinitanche controllare se il valore è anche Numero ed è più accurato per il controllo undefinedenull ecc ...

O puoi polyfill in questo modo:

Number.isFinite = Number.isFinite || function(value) {
  return typeof value === 'number' && isFinite(value);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.