Convert NaN to 0 in JavaScript
Asked Answered
D

11

328

Is there a way to convert NaN values to 0 without an if statement? Example:

if (isNaN(a)) a = 0;

It is very annoying to check my variables every time.

Disobedient answered 24/9, 2011 at 16:49 Comment(0)
P
768

You can do this:

a = a || 0

...which will convert a from any "falsey" value to 0.

The "falsey" values are:

  • false
  • null
  • undefined
  • 0
  • "" ( empty string )
  • NaN ( Not a Number )

Or this if you prefer:

a = a ? a : 0;

...which will have the same effect as above.


If the intent was to test for more than just NaN, then you can do the same, but do a toNumber conversion first.

a = +a || 0

This uses the unary + operator to try to convert a to a number. This has the added benefit of converting things like numeric strings '123' to a number.

The only unexpected thing may be if someone passes an Array that can successfully be converted to a number:

+['123']  // 123

Here we have an Array that has a single member that is a numeric string. It will be successfully converted to a number.

Printery answered 24/9, 2011 at 16:51 Comment(7)
The idea to turn the verification into a function is good, but this one is more elegant.Gasholder
@Bakudan: Good point. I was thinking OP was only concerned with the specific NaN value. This won't work as a test for all non number values. Although we could attempt a toNumber conversion first. I'll update.Printery
...ah, it's because of the title "Convert NaN to 0". Anyway, covered both ways now.Printery
Thanks mate, have selected and modified a bit this for myself a = a*1 || 0Vada
nullish coalescing operator (??) wouldn't yield the same in case you're using newer versions of javascript.Dermatosis
?? has a problem... if it is a NaN, e.g. parseInt('abc') ?? 10Locris
Note: this will convert -0 to 0 too.Ledford
A
48

Using a double-tilde (double bitwise NOT) - ~~ - does some interesting things in JavaScript. For instance you can use it instead of Math.floor or even as an alternative to parseInt("123", 10)! It's been discussed a lot over the web, so I won't go in why it works here, but if you're interested: What is the "double tilde" (~~) operator in JavaScript?

We can exploit this property of a double-tilde to convert NaN to a number, and happily that number is zero!

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

Approach answered 10/1, 2014 at 12:12 Comment(3)
Thanks, i didn't know about this ~~ at all, I just used it along side with parseFloat() like so: ~~parseFloat($variable);. Very neat :) +1Darell
WARNING: ~~20000000000 gives -1474836480Megalocardia
Heads up, parseFloat(4.567) returns 4.567 but ~~parseFloat(4.567) returns 4 so it loses the fractional part along with the decimal point.Clapperclaw
B
31

Write your own method, and use it everywhere you want a number value:

function getNum(val) {
   if (isNaN(val)) {
     return 0;
   }
   return val;
}
Beak answered 24/9, 2011 at 16:52 Comment(4)
If I pass in null then it does not give me the expected result of 0. More on my point here: https://mcmap.net/q/100706/-why-is-isnan-null-false-in-jsCost
Further to my comment above, I ended up using Number(val) instead as it returns 0 when it can't figure it out anyhow.Cost
@AndreiBazanov OP asks for "convert NaN to 0". While null is not NaN, why would you expecting it results 0?Ledford
@Ledford because this is JS we are dealing with, anything is possible :)Cost
W
14

Something simpler and effective for anything:

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

...which will convert a from any "falsey" value to 0.

The "falsey" values are:

  • false
  • null
  • undefined
  • 0
  • "" ( empty string )
  • NaN ( Not a Number )
Woodie answered 27/12, 2018 at 22:6 Comment(1)
Interesting! Just wondering how it reacts when val can be a negative value. As far as I've tested there is nothing wrong with this, but just in case...Treat
E
4

Rather than kludging it so you can continue, why not back up and wonder why you're running into a NaN in the first place?

If any of the numeric inputs to an operation is NaN, the output will also be NaN. That's the way the current IEEE Floating Point standard works (it's not just Javascript). That behavior is for a good reason: the underlying intention is to keep you from using a bogus result without realizing it's bogus.

The way NaN works is if something goes wrong way down in some sub-sub-sub-operation (producing a NaN at that lower level), the final result will also be NaN, which you'll immediately recognize as an error even if your error handling logic (throw/catch maybe?) isn't yet complete.

NaN as the result of an arithmetic calculation always indicates something has gone awry in the details of the arithmetic. It's a way for the computer to say "debugging needed here". Rather than finding some way to continue anyway with some number that's hardly ever right (is 0 really what you want?), why not find the problem and fix it.

A common problem in Javascript is that both parseInt(...) and parseFloat(...) will return NaN if given a nonsensical argument (null, '', etc). Fix the issue at the lowest level possible rather than at a higher level. Then the result of the overall calculation has a good chance of making sense, and you're not substituting some magic number (0 or 1 or whatever) for the result of the entire calculation. (The trick of (parseInt(foo.value) || 0) works only for sums, not products - for products you want the default value to be 1 rather than 0, but not if the specified value really is 0.)

Perhaps for ease of coding you want a function to retrieve a value from the user, clean it up, and provide a default value if necessary, like this:

function getFoobarFromUser(elementid) {
        var foobar = parseFloat(document.getElementById(elementid).innerHTML)
        if (isNaN(foobar)) foobar = 3.21;       // default value
        return(foobar.toFixed(2));
}
Eldest answered 4/4, 2014 at 22:34 Comment(0)
L
3

I suggest you use a regex:

const getNum = str => /[-+]?[0-9]*\.?[0-9]+/.test(str) ? parseFloat(str) : 0;

The code below will ignore NaN to allow a calculation of properly entered numbers:

const getNum = str => /[-+]?[0-9]*\.?[0-9]+/.test(str) ? parseFloat(str) : 0;

const inputsArray = [...document.querySelectorAll('input')];

document.getElementById("getTotal").addEventListener("click", () => {
  let total = inputsArray.map(fld => getNum(fld.value)).reduce((a,b)=>a+b);
  console.log(total)
});
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" disabled />
<button type="button" id="getTotal">Calculate</button>
Lice answered 25/1, 2018 at 16:28 Comment(0)
N
3

Methods that use isNaN do not work if you're trying to use parseInt(). For example,

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

But in the second case, isNaN produces false (i.e., the null string is a number).

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

In summary, the null string is considered a valid number by isNaN, but not by parseInt(). It was verified with Safari, Firefox and Chrome on macOS v10.14 (Mojave).

Nephelometer answered 15/1, 2020 at 23:26 Comment(3)
One obvious solution is a bit cumbersome, check for NaN after parseInt, not before: isNaN(parseInt(n)) ? parseInt(n) : 0; // calls parseInt twice :(Nephelometer
that comment should be (the beginning of) your answer!Mccants
A more efficient solution assumes that the null string is the only anomaly: n=="" || isNaN(n) ? 0 : parseInt(n); (but what if there are other strings?)Nephelometer
C
2

NaN is the only value in JavaScript which is not equal to itself, so we can use this information in our favour:

const x = NaN;
let y = x!=x && 0;
y = Number.isNaN(x) && 0

We can also use Number.isNaN instead of the isNaN function as the latter coerces its argument to a number

isNaN('string')        // true which is incorrect because 'string'=='string'
Number.isNaN('string') // false
Crozier answered 12/9, 2020 at 15:47 Comment(2)
Why is "NaN" weirdly syntax highlighted? Is the syntax highlighter correct or not?Cottrell
It is probably the syntax highlighter that is broken - "The global NaN property is a value representing Not-A-Number. ... NaN is a property of the global object.". Why, oh, why? What about using "Number.NaN"?Cottrell
B
1

    var i = [NaN, 1,2,3];

    var j = i.map(i =>{ return isNaN(i) ? 0 : i});
    
    console.log(j)
Besom answered 29/3, 2017 at 10:22 Comment(1)
An explanation would be in order. E.g., what is the idea/gist? From the Help Center: "...always explain why the solution you're presenting is appropriate and how it works". Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).Cottrell
I
1

Please try this simple function

var NanValue = function (entry) {
    if(entry=="NaN") {
        return 0.00;
    } else {
        return entry;
    }
}
Inert answered 31/8, 2017 at 7:15 Comment(1)
An explanation would be in order. E.g., what is the idea/gist? How and why is it different from previous answers (some use isNaN())? What input does it fail for? From the Help Center: "...always explain why the solution you're presenting is appropriate and how it works". Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).Cottrell
R
0

Using user113716's solution, which by the way is great to avoid all those if-else, I have implemented it this way to calculate my subtotal textbox from textbox unit and textbox quantity.

In the process writing of non-numbers in unit and quantity textboxes, their values are being replaced by zero, so the final posting of user data has no non-numbers.

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

<!--------- link above two 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"/>
Ruling answered 28/11, 2014 at 11:23 Comment(2)
What is "+$" for? A jQuery thing? Or something else?Cottrell
@PeterMortensen They're two separated things in this context: $ is part of the jQuery, and the + is used similar as in the accepted answer to convert to a number: a = +a || 0.Snowshed

© 2022 - 2024 — McMap. All rights reserved.