Why does isNaN(123.) return false? - javascript

Why does the Javascript function call isNaN(123.) return false? (notice the dot (.) after 123). Is this a universally acceptable number or will it cause errors downstream?
I'm validating whether a value is a valid decimal using isNaN along with split. Are there cross-browser issues with isNaN? Should I use a bespoke implementation?
Thanks.

In JavaScript the grammar of a Numeric Literal is expressed like this:
DecimalIntegerLiteral . DecimalDigitsopt ExponentPartopt
As you can see the DecimalDigits part after the dot is optional (opt suffix).
var n = 123.;
typeof n; // "number"
I wouldn't recommend the isNaN function to detect numbers, since type coercion can make some things look strange:
isNaN(""); // false, a empty string coerces to zero
isNaN("\n\t"); // false, a white-space string coerces to zero
isNaN(true); // false, boolean true coerces to 1
isNaN(false); // false, boolean false coerces to zero
isNaN(new Date); // false, Date objects coerce to its numeric timestamp
// etc...
isNaN should be used only to compare against NaN, since:
NaN == NaN; // false!
IsNaN(NaN); // true
If you want to detect Number objects, Number values or "parseable" numeric strings, give a look to this function I've posted some time ago.

NaN or (not a number) is a particular floating-point value, meaning a value that cannot be represented by computers (using the IEEE 754 floating point standard).
Crucially for you, the isNaN() function makes a best-effort to translate numbers to floating-point, which is why your example returns true. See, for example:
isNaN(100); //Returns false
isNaN("100"); //Returns false
isNaN("ABC"); //Returns true
isNaN("10C"); //Returns true
isNaN(Math.sqrt(-1)); //Returns true
If you want to access a number such as "123." as a float, try using parseFloat():
parseFloat("123."); //Returns 123
Furthermore, 123. is a valid number in javascript, which doesn't require a fractional part after the decimal point. So isNan() is behaving correctly, and should return false in this case.

The function is called "is Not a Number". So, this should return false in case you enter a number and true if it isn't. Even with the dot behind it this number is still valid. 123. just validates as 123 or 123.0.

Related

Why does Number(null) return 0, and parseFloat(null) return NaN?

I'm trying to write a helper function that will cast a String coming from an <input type="text" /> to a Number.
As I wasn't sure whether to use parseFloat(str) or Number(str) I doublechecked how they handle potentially problematic arguments.
See:
console.log(Number(null)); // 0
console.log(parseFloat(null)); // NaN
console.log(parseInt(null)); // NaN
console.log(isNaN(null)); // false
Both parseFloat and parseInt return NaN, whereas Number returns 0. Number seems more coherent here with isNaN(null).
Why is that?
Number constructor tries to coerce the argument to number. So empty string '', false, null and all falsy values become 0.
Similarly, Number(true) will return 1. Number('some string') will be NaN as 'some string' cannot be converted to a number.
Note that as pointed out in the comments, Number(undefined) is NaN and not 0 in arithmetic operations. (Read here https://codeburst.io/understanding-null-undefined-and-nan-b603cb74b44c)
Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
parseInt/Float convert their argument to a string, read it char by char from the left and try to make a number from what they've found. Since String(null) is "null" and a decimal number cannot start with "n", parseInt(null) will be NaN. If you provide a different base, where n, u and l are digits, the result will be different:
console.log(parseInt(null, 32))
Number converts its argument as a whole into a number. Number(null) returns +0 because the ECMA committee wants it to: http://www.ecma-international.org/ecma-262/7.0/#sec-tonumber . This is probably for historical reasons.
global isNaN (not to confuse with Number.isNaN) applies Number to its argument and returns true if the result is NaN. Since Number(null) is +0, isNaN(null) is false.
Hope this sheds some light...
NaN stands for "Not a Number". ParseFloat and ParseInt return real numbers and integers, so this is like an error returned by the function. Number(), on the other hand, represents the object's value. For instance, Number(false) will output 0.
The reason seems to be quite subtle with how parseInt and parseFloat work:
If the argument passed to parseInt/parseFloat is not a String (which null isn't), then it calls toString(null) which returns "[object Undefined]".
If the first character cannot be converted to a number, parseInt returns NaN.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt

EloquentJavaScript: !Number.isNaN() what is the purpose? [duplicate]

Soooooo isNaN is apparently broken in JavaScript, with things like:
isNaN('')
isNaN(' ')
isNaN(true)
isNaN(false)
isNaN([0])
Returning false, when they appear to all be... Not a Number...
In ECMAScript 6, the draft includes a new Number.isNaN but it looks like (imo) that this is also broken...
I would expect
Number.isNaN('RAWRRR')
To return true, since it's a string, and cannot be converted to a number... However...
It seems that things that I would consider... not a number, are indeed, not, not a number...
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isfinite-number
The examples on MDN say:
Number.isNaN("blabla"); // e.g. this would have been true with isNaN
I don't understand how this is "More robust version of the original global isNaN." when I cannot check to see if things are not a number.
This would mean we're still subjected to doing actual type checking as well as checking isNaN... which seems silly...
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-isnan-number
The ES3 draft here basically says, everything is always false, except with its Number.NaN
Does anyone else find this is broken or am I just not understanding the point of isNaN?
isNaN() and Number.isNaN() both test if a value is (or, in the case of isNaN(), can be converted to a number-type value that represents) the NaN value. In other words, "NaN" does not simply mean "this value is not a number", it specifically means "this value is a numeric Not-a-Number value according to IEEE-754".
The reason all your tests above return false is because all of the given values can be converted to a numeric value that is not NaN:
Number('') // 0
Number(' ') // 0
Number(true) // 1
Number(false) // 0
Number([0]) // 0
The reason isNaN() is "broken" is because, ostensibly, type conversions aren't supposed to happen when testing values. That is the issue Number.isNaN() is designed to address. In particular, Number.isNaN() will only attempt to compare a value to NaN if the value is a number-type value. Any other type will return false, even if they are literally "not a number", because the type of the value NaN is number. See the respective MDN docs for isNaN() and Number.isNaN().
If you simply want to determine whether or not a value is of the number type, even if that value is NaN, use typeof instead:
typeof 'RAWRRR' === 'number' // false
No, the original isNaN is broken. You are not understanding the point of isNaN.
The purpose of both of these functions is to determine whether or not something has the value NaN. This is provided because something === NaN will always be false and therefore can't be used to test this.
(side note: something !== something is actually a reliable, although counter-intuitive, test for NaN)
The reason isNaN is broken is that it can return true in cases when a value is not actually NaN. This is because it first coerces the value to a number.
So
isNaN("hello")
is true, even though "hello" is not NaN.
If you want to check whether a value actually is a finite number, you can use:
Number.isFinite(value)
If you want to test whether a value is a finite number or a string representation of one, you can use:
Number.isFinite(value) || (Number.isFinite(Number(value)) && typeof value === 'string')
As mentioned in a comment isNaN() and Number.isNaN() both check that the value you pass in is not equal to the value NaN. The key here is that NaN is an actual value and not an evaluated result e.g. "blabla" is a String and the value is "blabla" which means it is not the value "NaN".
A plausible solution would be doing something like:
Number.isNaN(Number("blabla")); //returns true.
The key difference between the two is that the global isNaN(x) function performs a conversion of the parameter x to a number. So
isNaN("blabla") === true
because Number("blabla") results in NaN
There are two definitions of "not a number" here and that's perhaps where the confusion lies. Number.isNaN(x) only returns true for the IEEE 754 floating point specification's definition of Not a Number, for example:
Number.isNaN(Math.sqrt(-1))
as opposed to determining whether the object being passed in is of numeric type or not. Some ways of doing that are:
typeof x === "number"
x === +x
Object.prototype.toString.call(x) === "[object Number]"
Basically, window.isNaN performs a type conversion to a number, then checks if it is NaN. Whereas, Number.isNaN doesn't try to convert its argument to a number. So basically, you can think of window.isNaN, and Number.isNaN as working like so.
window.isNaN = function(n){
return Number(n) !== Number(n);
}
window.Number.isNaN = function(n){
return n !== n;
}
Please note that you don't need actually to use the window. to call isNaN or Number.isNaN. Rather, I am just using it to provide a better distinction between the two similarly-named methods to try to cut down on confusion.
~ Happy Coding!
The following works because NaN is the only value in javascript which is not equal to itself.
Number.isNaN = Number.isNaN || function(value) {
return value !== value;
}
Per, MDN, it (NaN) is the returned value when Math functions fail and as such it is a specific value. Perhaps a better name would have been, MathFunctionFailed.
To determine if something is a number requires parsing which fails nicely over a broad range of non numeric inputs, successfully detecting numbers and strings representing numbers, hence:
function isNumber(v) {return Number.isNaN(parseFloat(v)); }
1. Number.isNaN
alert(Number.isNaN('Hello')); // false
Shouldn't it return true because Hello is a string and its Not A Number right ? But Lets know why it returns false.
MDN docs says :
true if the given value is NaN and its type is Number; otherwise,
false.
Yes Hello value is NaN but the type is string , you can check the type as follows:
alert(typeof `Hello`); // string
Usage:
Use when you want to check the value is both NaN and type is number.
2. isNaN
alert(isNaN('Hello')); // true
MDN docs says:
true if the given value is NaN; otherwise, false.
Usage:
Use when you want to check value is just NaN.
3. jQuery.isNumeric()
Jquery Docs Says :
Determines whether its argument represents a JavaScript number.
alert($.isNumeric('Hello')); // false
alert($.isNumeric(3)); //true
Usage:
Use when you want to check value is a number or can be converted to a number.
Reference
I use a simple workaround to check Number.isNaN():
let value = 'test';
Number.isNaN(-value); // true
value = 42;
Number.isNaN(-value); // false
js trying to convert the value to the negative Number, if the conversion is failed - we have NaN.
Simple, isn't it?
Moreover, online benchmark tests say Number.isNaN is lighter than isNaN.
Number.isNaN(x) checks if x is directly evaluated to NaN or not.
RAWR is not the same as NaN. Think of NaN as an entity to represent the result of some mathematical calculation where the computer does not know how to represent the number.
A mathematical operation is not going to yield a non-numeric result, hence the typeof NaN is number.
The string RAWR had undergone no mathematical operation to yield NaN. However, if you were to call Number.isNaN(+'RAWR'), it would result in NaN since the unary + operator is trying to convert 'RAWR' to a number.
On the other hand, isNaN(y) tells whether y can be converted to a number or not. If isNaN(y) is false, y can be converted to a number. But if isNaN(y) is true, y can not be converted to a number.
So a good rule of thumb is:
Do I want to check if x can be successfully converted to a number? Use isNaN(x) == false in that case. Unsuccessful conversion results in NaN.
Do I want to check if x is evaluated to NaN? Use Number.isNaN(x) == true for that.
#phill, as stated in other responses, neither is broken.
Number.isNaN work on a number or instance of Number, so even Number.isNaN(new Date(NaN)) is false.
isNaN, on the other hand, is generic and tries to convert its parameter to a number before checking it.
If you want to determine if a value is (or contains) NaN, you can use this function:
function valueIsNaN(value) {
// eslint-disable-next-line no-self-compare
return value !== value || typeof value == 'object' && Number.isNaN(value.valueOf());
}

why does "Infinity==Infinity" in JavaScript becomes true?

As far as I know, in math both Infinity and NaN are vague values.
as all of us know:
console.log(NaN == NaN); //-> false
while
console.log(Infinity==Infinity); //-> true
I'm wondering why the result of the second code is true. I'm expecting that the result of the second one, should be false, but it's not.
Could you please help me out.
I'd really appreciate it. Thanks.
This is why:
NaN compares unequal (via ==, !=, ===, and !==) to any other value -- including to another NaN value. Use Number.isNaN() or isNaN() to most clearly determine whether a value is NaN. Or perform a self-comparison: NaN, and only NaN, will compare unequal to itself.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN
The initial value of Infinity is Number.POSITIVE_INFINITY. The value Infinity (positive infinity) is greater than any other number. This value behaves mathematically like infinity; for example, any positive number multiplied by Infinity is Infinity, and anything divided by Infinity is 0.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity
What you also might be interested in is using the isFinite method of Number:
Number.isFinite(Infinity); // false
Number.isFinite(NaN); // false
Read up on Number.isFinite(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite
In addition to the other answers: Because the spec says so.
NaN is the only value in JavaScript that is not equal to itself:
A reliable way for ECMAScript code to test if a value X is a NaN is an expression of the form X !== X. The result will be true if and only if X is a NaN.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4
Because processors interpret it that way. Most math in JS follows the IEEE-754 specification for floating math arithmetic, which processors implement in pretty specific ways. That includes NaN !== NaN and Infinity === Infinity, among other things.
infinity is treated as a numeric value, so infinity==infinity represents one numeric value equaling another. While in common mathematics the infinity can not be compared against infinity, in javascript it can!
NaN on the other hand, is a type of undefined variable, not a number. So comparisons between NaN are not logically comparable. The proper way to compare against NaN is with the function isNaN.
Example:
isNaN(NaN) // returns true

Why does Javascript isNaN function declare string negative hex values to be NaN?

Given the following example:
isNaN("-0x123"); // returns true , meaning is not a number <- Why?
isNaN(-0x123); // returns false, meaning is a number
isNaN("0x123"); // returns false, meaning is a number
parseInt("-0x123"); // returns -291
My question: why does isNaN declares negative hex strings as NaN when other similar inputs yield more reasonable outputs?
Thanks
The function isNaN() tells you whether or not a value may be coerced to a number, it says nothing about whether there exists a function that will convert the value to a number.
You will see the same behaviour if you attempt to coerce the strings to numbers:
> +"-0x123"
NaN
> +(-0x123)
-291
> +"0x123"
291
The first case you have a string that does not match Javascript's rules for a number as that doesn't allow for a leading - on a hex literal, the second case you have an expression that evaluates to a number (so 0x123 negated), the third case you have a string that does match the grammar for a number.
See http://www.ecma-international.org/ecma-262/5.1/#sec-9.3 for the exact description, but in short a string numeric literal may be an unsigned decimal literal, + or - followed by an unsigned decimal literal, or it may be a hex integer literal (and in all these cases leading and trailing whitespace is ignored). There is no option for a sign on a hex literal.
What you are expecting is this :
isNaN(parseInt("-0x123")); // returns -291
Because "-0x123" is treated as a string and not as a number. So
isNaN("-0x123");
will return false since there is no number. The MDN says:
The isNaN() function determines whether a value is NaN or not. Note:
coercion inside the isNaN function has interesting rules; you may
alternatively want to use Number.
.........
Confusing special-case behavior
Since the very earliest versions of the isNaN function specification,
its behavior for non-numeric arguments has been confusing. When the
argument to the isNaN function is not of type Number, the value is
first coerced to a Number. The resulting value is then tested to
determine whether it is NaN. Thus for non-numbers that when coerced to
numeric type result in a valid non-NaN numeric value (notably the
empty string and boolean primitives, which when coerced give numeric
values zero or one), the "false" returned value may be unexpected; the
empty string, for example, is surely "not a number." The confusion
stems from the fact that the term, "not a number", has a specific
meaning for numbers represented as IEEE-754 floating-point values. The
function should be interpreted as answering the question, "is this
value, when coerced to a numeric value, an IEEE-754 'Not A Number'
value?"

Javascript if-statement vs. comparsion

Is it true that in if-statement JavaScript wrap the condition into a Boolean?
if(x) => if(Boolean(x))
Is it true that in comparison JavaScript wrap the compare elements into a Number?
a == b => Number(a) == Number(b)
Yes, and No.
For the first part, yes, that is essentially what the javascript does.
But for the latter, no. Not everything in JavaScript can be converted to a number. For example:
Number('abc') // => NaN
And Not-A-Numbers are not equal:
NaN == NaN // => false
So something like this:
Number('abc') == Number('abc') // => false!
But that's actually true with equality comparison.
'abc' == 'abc' // => true
As a side note, it's probably better to use === in JavaScript, which also checks the type of the values being compared:
0 == '0' // => true
0 === '0' // => false, because integer is not a string
More details about === can be read over here.
Yes, that's true, x is evaluated in a boolean context in this situation, so the equivalent of Boolean(x) is applied.
No, that's not true. It only looks that way because the coercitive equality operator == tries to convert a and b to the same type. Number() is only applied if either a or b is already a Number. For instance:
>>> 0x2A == 42
true // both 'a' and 'b' are numbers.
>>> "0x2A" == 42
true // 'a' is a string whose number coercion is equal to 'b'.
>>> "0x2A" == "42"
false // 'a' and 'b' are different strings.
Is it true that in if-statement JavaScript wrap the condition into a Boolean?
Usually yes.
Is it true that in comparison JavaScript wrap the compare elements into a Number?
Absolutely no.
Explanation
From JavaScript Language Specifications.
The if statement is defined at § 12.5 as:
if ( Expression ) Statement else Statement
It says that the Expression will be evaluated, converted with GetValue() and then tested after the ToBoolean() conversion.
Then the first assertion is true (but see later), the condition for the if statement is evaluated like is passed as parameter to the Boolean function. Please recall how JavaScript handles type conversion to boolean (§ 9.2):
undefined and null values are converted to false.
numbers are converted to false if ±0 or NaN otherwise they're converted to true.
strings are converted to false if empty otherwise always to true regardless their content.
objects are always converted to true.
Because of the call to GetValue() strictly speaking this assertion is not always true, take a look to § 8.7.1 where the standard describes how GetValue() works, here can happen some magic conversion before ToBoolean() is called.
The == operator is defined as in § 11.9.3.
As you can see it doesn't specify that operands must be (or will be treated as) numbers, the behavior of the operator is different and regulated by a series of rules based on the type of the operands. Then your second assertion is false. The case they're numbers (or one of them is a number) is just a special case in the algorithm, please note that at point 4 of the algorithm it says that if one of them is a number and the other one is a string then it'll be converted with ToNumber(), only in this case (with all the implications that this conversion has).
It's intuitive if you think that you can compare functions, strings or numbers, not every type can be converted to a numeric value.

Categories

Resources