Konwertuj NaN na 0 w javascript

238

Czy istnieje sposób na konwersję wartości NaN na 0 bez instrukcji if:

if (isNaN(a)) a = 0;

Sprawdzanie moich zmiennych za każdym razem jest bardzo denerwujące.

Tamás Pap
źródło
4
Czy nie możesz po prostu uratować go w funcion?
the_drow 24.09.11
To tylko 20 znaków, w czym problem?
Rusty Fausak
1
function noNaN( n ) { return isNaN( n ) ? 0 : n; }a potem tylkonoNaN( a )
Šime Vidas
1
@rfausak Na ogół nie chcesz się powtarzać (patrz DRY ). Jeśli określona funkcja jest potrzebna wiele razy, preferowana jest funkcja dedykowana.
Šime Vidas

Odpowiedzi:

575

Możesz to zrobić:

a = a || 0

... który zamieni dowolną wartość „falsey” na 0.

Wartości „falsey” to:

  • false
  • null
  • undefined
  • 0
  • "" ( pusta struna )
  • NaN (Nie liczba)

Lub to jeśli wolisz:

a = a ? a : 0;

... które będą miały taki sam efekt jak powyżej.


Jeśli celem było przetestowanie czegoś więcej niż tylko NaN, możesz zrobić to samo, ale najpierw wykonać konwersję do liczby .

a = +a || 0

To używa operatora unary +, aby spróbować przekonwertować ana liczbę. Ma to tę dodatkową zaletę, że konwertuje takie rzeczy, jak ciągi liczbowe '123'na liczbę.

Jedyną nieoczekiwaną rzeczą może być sytuacja, gdy ktoś przejdzie przez tablicę, którą można z powodzeniem przekonwertować na liczbę:

+['123']  // 123

Tutaj mamy tablicę, która ma pojedynczy element, który jest ciągiem liczbowym. Zostanie pomyślnie przekonwertowany na liczbę.

użytkownik113716
źródło
Pomysł przekształcenia weryfikacji w funkcję jest dobry, ale ten jest bardziej elegancki.
Tamás Pap
1
@Bakudan: Dobra uwaga. Myślałem, że OP dotyczy tylko konkretnej NaNwartości. To nie zadziała jako test dla wszystkich wartości nieliczbowych. Chociaż moglibyśmy najpierw spróbować wykonać konwersję liczby. Zaktualizuję.
user113716 24.09.11
... ah, to z powodu tytułu „Konwertuj NaN na 0” . W każdym razie, objął teraz obie strony.
user113716 24.09.11
2
Dzięki kolego, wybrałem i zmodyfikowałem trochę to dla siebie a = a * 1 || 0
Ktoś
Niesamowite. Dzięki
Apit John Ismail
32

Używanie podwójnej tyldy (podwójnie bitowe NIE) - ~~- robi kilka interesujących rzeczy w JavaScript. Na przykład możesz użyć go zamiast Math.floorlub nawet jako alternatywy dla parseInt("123", 10)! Dużo się o tym mówi w Internecie, więc nie będę się zastanawiał, dlaczego tu działa, ale jeśli jesteś zainteresowany: co to jest operator „podwójnej tyldy” (~~) w JavaScript?

Możemy wykorzystać tę właściwość podwójnej tyldy do konwersji NaNna liczbę i na szczęście ta liczba wynosi zero!

console.log(~~NaN); // 0

WickyNilliams
źródło
1
Dzięki, nie wiedziałem o tym ~~w ogóle, po prostu stosować go wraz z boku parseFloat()tak: ~~parseFloat($variable);. Bardzo schludnie :) +1
Rens Tillmann
23

Napisz własną metodę i używaj jej wszędzie tam, gdzie chcesz wartość liczbową:

function getNum(val) {
   if (isNaN(val)) {
     return 0;
   }
   return val;
}
Saket
źródło
1
Jeśli przejdę, nullto nie da mi oczekiwanego rezultatu 0. Więcej o moim punkcie tutaj: stackoverflow.com/questions/115548/why-is-isnannull-false-in-js
Andrei Bazanov
2
W związku z powyższym komentarzem skończyło się Number(val)na tym, że powraca, 0gdy i tak nie może tego zrozumieć.
Andrei Bazanov,
4

Coś prostszego i skutecznego na wszystko:

function getNum(val) {
   val = +val || 0
   return val;
}

... który zamieni dowolną wartość „falsey” na 0.

Wartości „falsey” to:

  • false
  • null
  • undefined
  • 0
  • "" ( pusta struna )
  • NaN (Nie liczba)
Woold
źródło
1
Ciekawy! Zastanawiam się tylko, jak zareaguje, gdy val może być wartością ujemną. O ile testowałem, nie ma w tym nic złego, ale na wszelki wypadek ...
Luciano
2

Zamiast kludować, aby móc kontynuować, dlaczego nie wykonać kopii zapasowej i zastanawiać się, dlaczego w ogóle napotykasz NaN?

Jeśli którykolwiek z numerycznych danych wejściowych operacji jest NaN, wyjście będzie również NaN. Tak właśnie działa obecny standard zmiennoprzecinkowy IEEE (to nie tylko Javascript). Takie zachowanie jest nie bez powodu : podstawową intencją jest powstrzymanie cię od wykorzystywania fałszywego wyniku bez uświadomienia sobie, że jest fałszywy.

Sposób działania NaN polega na tym, że jeśli coś pójdzie nie tak w niektórych poddziałaniach podrzędnych (wytwarzając NaN na tym niższym poziomie), końcowym wynikiem będzie również NaN, który natychmiast rozpoznasz jako błąd, nawet jeśli twój logika obsługi błędów (może rzucać / łapać?) nie jest jeszcze ukończona.

NaN jako wynik obliczeń arytmetycznych zawsze wskazuje, że coś poszło nie tak w szczegółach arytmetyki. W ten sposób komputer może powiedzieć „potrzebne jest tutaj debugowanie”. Zamiast znaleźć sposób na kontynuację z jakąś liczbą, która prawie nigdy nie jest poprawna (czy 0 naprawdę jest tym, czego chcesz?), Dlaczego nie znaleźć problemu i go naprawić.

Częstym problemem jest to, że zarówno JavaScript parseInt(...)i parseFloat(...)zwróci NaN jeśli otrzymują bezsensowny argument ( null, ''itp). Napraw problem na najniższym możliwym poziomie, a nie na wyższym poziomie. Zatem wynik ogólnego obliczenia ma dużą szansę na sens i nie zastępujesz żadnej magicznej liczby (0 lub 1 lub cokolwiek innego) wynikiem całego obliczenia. (Sztuczka (parseInt (foo.value) || 0) działa tylko w przypadku sum, a nie produktów - w przypadku produktów, których wartość domyślna ma wynosić 1, a nie 0, ale nie, jeśli podana wartość naprawdę wynosi 0.)

Być może dla ułatwienia kodowania chcesz, aby funkcja pobierała wartość od użytkownika, czyściła ją i, w razie potrzeby, podała wartość domyślną:

function getFoobarFromUser(elementid) {
        var foobar = parseFloat(document.getElementById(elementid).innerHTML)
        if (isNaN(foobar)) foobar = 3.21;       // default value
        return(foobar.toFixed(2));
}
Chuck Kollars
źródło
2

Co powiesz na regex ?

function getNum(str) {
  return /[-+]?[0-9]*\.?[0-9]+/.test(str)?parseFloat(str):0;
}

Poniższy kod zignoruje NaN, aby umożliwić obliczenie poprawnie wprowadzonych liczb

mplungjan
źródło
2

Metody, które używają isNaN, nie działają, jeśli próbujesz użyć parseInt, na przykład:

parseInt("abc"); // NaN
parseInt(""); // NaN
parseInt("14px"); // 14

Ale w drugim przypadku isNaN produkuje fałsz (tzn. Ciąg zerowy jest liczbą)

n="abc"; isNaN(n) ? 0 : parseInt(n); // 0
n=""; isNaN(n) ? 0: parseInt(n); // NaN
n="14px"; isNaN(n) ? 0 : parseInt(n); // 14

Podsumowując, łańcuch zerowy jest uważany za prawidłową liczbę przez isNaN, ale nie przez parseInt. Sprawdzone w Safari, Firefox i Chrome na OSX Mojave.

David Crowe
źródło
1
Jedno oczywiste rozwiązanie jest nieco kłopotliwe, sprawdź NaN po analizie, a nie wcześniej: isNaN (analizie (n))? parseInt (n): 0; // wywołuje parsowanie dwa razy :(
David Crowe
1
ten komentarz powinien być (początkiem) twojej odpowiedzi!
frandroid
Bardziej wydajne rozwiązanie zakłada, że ​​ciąg zerowy jest jedyną anomalią: n == "" || isNaN (n)? 0: parseInt (n); (ale co jeśli są inne łańcuchy?)
David Crowe
1
var i = [NaN, 1,2,3];

var j = i.map(i =>{ return isNaN(i) ? 0 : i});

console.log(j)

[0,1,2,3]

KARTHIKEYAN.A
źródło
0

za pomocą rozwiązania 113716 użytkownika, które, nawiasem mówiąc, jest świetne, aby uniknąć tych wszystkich, jeśli-inaczej wdrożyłem go w ten sposób, aby obliczyć sumę częściową pola tekstowego z jednostki pola tekstowego i ilości pola tekstowego.

W procesie pisania liczb nie będących liczbami w polach tekstowych jednostek i ilości, ich wartości są zastępowane przez zero, więc końcowe księgowanie danych użytkownika nie zawiera żadnych liczb.

     <script src="/common/tools/jquery-1.10.2.js"></script>
     <script src="/common/tools/jquery-ui.js"></script>

     <!----------------- link above 2 lines to your jquery files ------>





    <script type="text/javascript" >
    function calculate_subtotal(){

    $('#quantity').val((+$('#quantity').val() || 0));
    $('#unit').val((+$('#unit').val() || 0));

    var  calculated = $('#quantity').val() * $('#unit').val() ;
    $('#subtotal').val(calculated);


    }
    </script>


      <input type = "text" onChange ="calculate_subtotal();" id = "quantity"/>
      <input type = "text" onChange ="calculate_subtotal();" id = "unit"/>
      <input type = "text" id = "subtotal"/>
webzy
źródło
0

Spróbuj tej prostej funkcji

var NanValue = function (entry) {
    if(entry=="NaN") {
        return 0.00;
    } else {
        return entry;
    }
}
subindas pm
źródło