0

I am slightly confused on the logical NOT operator in Javascript (!). From my understanding, this is mainly used to "inverse" a boolean value. For example, if an expected output of a boolean is true, putting this in front would turn it to false, and vice versa.

In my below code, I created a function allowing user to input a lower and upper integer, and the function would generate a random number between this range. If, however, the user inputs a string instead of an integer, it will prompt the user to enter an integer instead.

I am using isNaN to check if user's input is an integer, and using logical NOT operator in front of it to inverse the result.

In my if condition, if I check isNaN for lower && isNaN for upper are both not a number, this program seems to work correctly. However, if I use ||, it doesn't work as expected, as shown in my code below.

Why is this so? By using OR operator, I am saying if either upper or lower is NaN, then prompt the user to enter a valid integer. Why is it a && and not a || when only one condition needs to be true?

const getNumber = function(lower, upper) {
  if ( !isNaN(lower) || !isNaN(upper) ) {
  const number = Math.floor(Math.random() * (upper - lower + 1)) + lower;
  return number;
  } else {
  alert("Please enter a valid integer.");
  }
};

// Call the function and pass it different values
console.log( getNumber('six',5) );
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Pete
  • 117
  • 3
  • NaN does not check if a string is a number. You have to parse it first. Then, the parsing result may be NaN if it could not be parsed – Random Mar 13 '21 at 10:29
  • `console.log(isNaN("six"), isNaN(5))` – pishpish Mar 13 '21 at 10:29
  • 1
    @Random - `isNaN` will use implicit string->number parsing if you pass it a string. (In contrast, `Number.isNaN` won't.) – T.J. Crowder Mar 13 '21 at 10:29
  • If you want to use `OR` you need to remove the `NOT` - Using `isNan` here is somewhat of a double negative situation, so you either want x AND y are both NOT isNan, or x OR y isNan – pilchard Mar 13 '21 at 10:30

2 Answers2

3

It's not the ! operator that's the problem, it's ||. if ( !isNaN(lower) || !isNaN(upper) ) { says (roughly) "if lower is a number or upper is a number". But you don't wan to say "or" there, because you want them both to be numbers.

So either use use && (and):

if ( !isNaN(lower) && !isNaN(upper) ) {
// −−−−−−−−−−−−−−−−^^
    const number = Math.floor(Math.random() * (upper - lower + 1)) + lower;
    return number;
} else {
    alert("Please enter a valid integer.");
}

or reverse the content of your if and else blocks and use || without !:

if ( isNaN(lower) || isNaN(upper) ) {
    alert("Please enter a valid integer.");
} else {
    const number = Math.floor(Math.random() * (upper - lower + 1)) + lower;
    return number;
}

Side note: You're using implicit string-to-number parsing in your code. I recommend doing it on purpose. My answer here goes into your various options for parsing numbers and their pros and cons.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

By using OR, you are checking that at least one value should not be NaN.

let a = !isNaN(lower);
let b = !isNaN(upper);

a and b can be either true or false. When you use ||, you are telling that at least one of this values should be true. If you check Truth table, you will see that OR will be true for this combitations of a and b:

  • a == true, b == true
  • a == false, b == true
  • a == true, b == false

What you want is to check that a == true and b == true simultaneously - so you have to use AND (&&) which will evaluate to true if and only if a == true and b == true.

Mr. Hedgehog
  • 2,644
  • 1
  • 14
  • 18