31

I came across the goog.math.isFiniteNumber function in the Google Closure Library. What it does is checking whether a given number is both finite and not NaN.

The underlying code is:

goog.math.isFiniteNumber = function(num) {
  return isFinite(num) && !isNaN(num);
};

So, first it checks whether the number is finite using the native isFinite function, and then does an additional check to make sure the number isn't NaN using isNaN.

However, isFinite already returns false in case the argument is NaN. So, what advantages does the check for isNaN provide?

pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • I think you should ask the author of the code. My best guess is that some buggy (old?) browser treats `NaN` as finite and the double check is for compatibility only. – Ferdinand Beyer Apr 16 '11 at 22:37
  • 2
    It could be some obscure browser (or other javascript implementation) that gets it wrong, the programmer assuming isFinite only tested for +/- infinity, or the programmer just specifying an extra check as a precaution. – Jason Goemaat Jun 16 '11 at 19:50

5 Answers5

23

The only difference is this:

!isNan(1/0) // --> true
isFinite(1/0) // --> false

isNaN checks whether the argument is a number or not. The Infinities (+/-) are also numerical, thus they pass the isNaN check, but don't pass the isFinite check.

** Note that any string which can be parsed as a number ("2", "3.14") will cause isNaN to return false.

Hope this helps.

PS: The answer given by user1170379 was very nearly perfect.

kumarharsh
  • 18,961
  • 8
  • 72
  • 100
  • 2
    So, to answer OP's question, *yes*, the `isNaN` check is redundant. – Jamie Jan 29 '15 at 01:19
  • @Jamie is absolutely is **not** redundant. If it was, it wouldn't have been there. Say you want to check for Infinity. which is a valid number (there can be cases where you're incorporating Infinities into your logic, say in a Maths application). There, `!isNaN()` would return true but isFinite would be false. – kumarharsh Jan 29 '15 at 07:15
  • 6
    Yep, everything you've said is correct. `!isNaN(Infinity) === true`, and `isFinite(Infinity) === false`. So, `isFinite(num) && !isNaN(num) === false`. That's why the `isNaN` check is redundant - `isFinite` captures both the `NaN` and `Infinity` failure cases. – Jamie Jan 30 '15 at 01:04
  • Holy smoke, I always assumed `1/0` would evaluate to `NaN`, but I checked it just now and it returns `Infinity`. `0/0`, on the other hand, comes out to `NaN`. Even more surprising, [Wolfram Alpha agrees!](https://www.wolframalpha.com/input/?i=1%2F0) Can anyone help me understand this? – Justin Morgan - On strike Jul 13 '15 at 19:30
3

you might reason out [Why?] after reading this:

NaN doesn't check if the passed value is infinite or not - it checks if the input val evaluates into a "Type: Number" end-result. Because isNaN(string) is accepted, so the: isNaN("3.14") //false (which means true, the given token is duck converted into a type Number successfully )

You may understand that the input value may happen to be an unresolved brute number, even a math operation as simple as: (x/y); which in turn might yield a (+/-infinity) number.

Here x=1, y=0; meaning (1/0).Then isNaN(x/y) will first evaluate to isNaN(1/0); then to isNaN(infinity) //false. Since (1/0)=infinity is of type: "number" ie typeof(1/0) //"number" isNaN should and will return false.

You don't want to put "infinity" where an end result number is expected.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • 4
    What does `typeof` have to do with `isNaN`? `isNaN` merely returns true when passed a value that coerces to the numeric value corresponding to IEEE-754 NaN. `isNaN` is equivalent to `function isNaN(x) { x = +x; return x !== x; }`. – Mike Samuel Jan 26 '12 at 00:27
  • sorry Samuel but you didn't grasp the half of it and your function for isNaN should be: **function isNaN(x){return x!=x}** and not a byte more. –  Feb 07 '12 at 04:59
  • Samuel's answer is an excellent explanation of how the isNaN function is *actually* implemented; user1170379's suggestion is how most of us *wish* it were implemented. For further proof, `x={}`, `isNaN(x)=>true` but `x!=x=>false` – elreimundo Mar 13 '15 at 18:45
1

isNaN() returns true if the argument is not a number or if the argument is a non-numeric value such as a string or an object.Otherwise, It returns false. Example: isNaN(0/0) =>true; isNaN(2-1) =>false; isFinite() returns true if the argument is a number other than NaN,Infinity or -Infinity.Otherwise, It returns false. Example: isFinite("2000") =>false; isFinite(200/2) =>true;`

Sri Dasari
  • 42
  • 2
  • 5
1

Probably for the same reason that I have implemented (isfinite(num) && isfinite(-num)) - I was getting errors from mysql complaining about putting "-nan" into the database even though I had a check for isfinite(field)...

A useful article on this subject is http://jacksondunstan.com/articles/983 which provides an optimization ((d*0.0)==0.0)

Rupert
  • 79
  • 3
-5

If isFinite worked the way isFiniteNumber did, then there would be no reason to write isFiniteNumber. There's probably some browser out there somewhere that treats NaN as finite.

Zach Rattner
  • 20,745
  • 9
  • 59
  • 82
  • I'm wondering which one it might be. Chrome/IE9/Firefox/Opera all behave correctly. Perhaps IE6, but I guess the `isFinite` function is sufficient in all cases. – pimvdb Apr 16 '11 at 23:08
  • 1
    Microsoft claims IE6 supports it: http://msdn.microsoft.com/en-us/library/h5s8dazc(v=vs.94).aspx – Zach Rattner Apr 16 '11 at 23:11
  • 8
    I'm sorry to say, but this answer is not correct. This is based on just conjecture. – kumarharsh May 30 '13 at 15:43
  • This answer may be conjecture, but it does address the actual question, which is about the fact that, by definition, isNaN is implicit in isFinite. The isNaN call should be pointless -- *unless* there's a browser out there with an implementation error. But I suspect this is a Closure mistake. I can't find any examples of broken isFinite implementations with Google, and it's notable that elsewhere in the same file, they feel comfortable with the assumption that any value passing isFinite must be a number: `goog.math.isInt = function(num) { return isFinite(num) && num % 1 == 0; };` – Semicolon Sep 02 '14 at 03:56
  • (An aside though -- while all implementations I've checked seem to use isNaN inside isFinite, as expected, isNaN itself is weird as hell -- for example ' ' evaluates to the number zero. That's why underscore uses `_.isFinite = function(obj) { return isFinite(obj) && !isNaN(parseFloat(obj)); };`) – Semicolon Sep 02 '14 at 04:07