Why is Infinity a number? [duplicate] - javascript

This question already has answers here:
Infinity is some number in javascript?
(3 answers)
Closed 6 years ago.
In JavaScript, isNaN(Infinity) returns false, as if Infinity were a number; but several arithmetic operations on Infinity behave as if it were the mathematical infinity, which is not a number:
So, why doesn't isNaN(Infinity) return true? Is it because its value defaults to a Number object?

Infinity is not NaN because you are able to use it in mathematical expressions. Obviously 1 + NaN would never work, but 1 + Infinity returns Infinity (See here). Many of the examples that you have in your link are mathematically indeterminate, which is why they return as Nan. For example, Infinity * 0 is indeterminate (See here).
Hope this helps.

The reason isNaN(Infinity) returns false has nothing to do with mathematical technicalities, it's simply because its implementation is equal to this:
function isNaN(object) {
var coerced = +object;
return coerced !== coerced;
}
In other words, it coerces the input to a Number. If the coerced value is determined to be NaN (by checking if it is not strictly equal to itself), then it returns true. Otherwise it returns false.
[Infinity, null, undefined, true, new Date(), {}, [], [1], [1,2,3], 'blah', '4'].forEach(function (object) {
console.log('object: ' + (typeof object !== 'number' ? JSON.stringify(object) : object));
console.log('coerced: ' + (+object));
console.log('isNaN: ' + isNaN(object));
console.log('==================');
});

Related

Why does an empty array plus false in JS return a string?

Why does an empty array plus false return the string "false"?
> [] + false
> "false"
An empty array is false, right?
Then false + false = false? No?
Short answer: because the spec says so.
Longer answer: When the left operand of the + operator is not a string or a number, the operand will be converted to either one of those depending on their "preferred" primitive type (defined in the spec). The array's "preferred" type is a string and [].toString() is an empty string.
Then, still according to the spec, because the left operand is a string (following the previous conversion), the right operand will be converted to a string and the result of the + operation will be the concatenation of both strings.
In other words, [] + false is equivalent to [].toString() + false.toString() (or "" + "false") and results in the string "false".
Other interesting results as a consequence of this:
[1,2,3] + false // "1,2,3false"
[1,[2]] + false // "1,2false"
[] + {} // "[object Object]"
The '+' operator casts to string or number (whatever is possible).
It doesn't cast to Boolean, check it out for yourself:
const x = [] + false;
const y = false + false;
console.log(typeof(x)); // string
console.log(typeof(y)); // number
The general rule for addition in JavaScript is simple: You can only add numbers and strings, all other values will be converted to either one of those types.
Source: https://2ality.com/2012/11/coercing-objects.html
First the + operator must make sure that it operates on primitives (either numbers or strings). If an operand isn't a primitive it must first convert it.
Here are the rules:
If the operand is a primitive then stop.
Otherwise call its .valueOf() method. If the return value is a primitive then stop.
Otherwise call its .toString() method.
In [] + false, [] isn't a primitive. Let's convert it:
([]).valueOf(); //=> [] (not a primitive)
([]).toString(); //=> "" (primitive)
We now have "" + false to solve.
If any operand is a string, then + returns the concatenation of both operands. Meaning that false must be converted to a string:
(false).toString(); //=> "false"
The final operation becomes "" + "false" which returns "false".
What does false + false return?
Both operands are primitives and both aren't strings. So they must both be converted to numbers.
Number(false); //=> 0
+false; //=> 0
Therefore false + false becomes 0 + 0 which returns 0.
How to make [] + false returns 42?
Simple:
Force [] to return 42
42 + false will cause false to be coerced into a number: 0
42 + 0 returns 42
Example:
var empty_arr = [];
empty_arr.valueOf = () => 42;
console.log(empty_arr + false);
Or: (but that's nasty)
Array.prototype.valueOf = () => 42;
console.log([] + false);
Basically it's because JS is trying to concat an array and then adds the string. Take a look on this:
[1] + true // "1true"
[2] + 5 // "25"
[2, 3, 4] + 5 // "2,3,45"
Similar to:
"".concat([3, 2, 1]); // "3,2,1"
More info: Why is [1,2] + [3,4] = "1,23,4" in JavaScript?

why do parseInt and isNaN in JavaScript have inconsistent behavior?

I'm using node.js with v8.11.3.
parseInt("") returns NaN, but isNaN("") returns false:
console.log(
parseInt(''),
isNaN('')
);
another example:
console.log(
parseFloat('0x5'),
parseInt('0x5')
);
Per MDN docs, parseInt:
If the first character cannot be converted to a number, parseInt returns NaN.
There is no first character in the empty string - it cannot be converted to a number, so NaN is returned.
But isNaN is different. As the first paragraph of MDN says:
Note: coercion inside the isNaN function has interesting rules; you may alternatively want to use Number.isNaN(), as defined in ECMAScript 2015.
...
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number.
The empty string, when coerced to a Number, is 0:
const result = Number('');
console.log(result + ' : ' + typeof result);
You might try using parseInt and then checking to see if the result is NaN or not:
const possibleInt = parseInt('');
console.log(Number.isNaN(possibleInt));
The use of Number() just shuffles the problem around. For example:
parseInt("14px"); // 14
parseInt("abc"); // NaN
parseInt(""); // NaN (i.e. null string is a number)
versus use of isNaN:
isNaN("14px"); // false
isNaN("abc"); // true
isNaN(""); // false
versus use of Number():
Number("14px"); // NaN
Number("abc"); // NaN
Number(""); // 0
And, making it more complicated, you can't even do:
parseInt(x) == NaN ? 0 : parseInt(x);
because comparisons with NaN are always false, even NaN == NaN is false.
The simplest that I found was:
x=="" || !isNaN(x) ? 0 : parseInt(x);
but this assumes that the null string is the only anomaly, so it may not work in all cases.

How to Convert nAn to 0 [duplicate]

This question already has answers here:
Convert NaN to 0 in JavaScript
(11 answers)
Closed 9 years ago.
Array with json
how to convert isNaN to number zero
so if you ahve array 1,2,3 and subtract 1,2 how to subtract
1-1
2-2
3- NaN
NaN should be 0 for 3-0
// Create variables to append player's + or - score per hole
var golfStroke = scores[y].strokes[q];
var parStroke = pars[z];
var scoreStroke = parStroke - golfStroke;
// Create if statement to change undefined array values to number 0 for calculation
var isNum = function () {
if (isNaN(golfStroke)) {
return 0;
} else {
return golfStroke;
}
if (isNaN(parStroke)) {
return 0;
} else {
return parStroke;
};
}
console.log("The over or minus par is: " + scoreStroke);
Thanks
A simple shorthand way of using 0 if you have NaN is to use JavaScript's curiously-powerful || operator:
var x = somethingThatMayBeNaN || 0;
Since NaN is falsey, if somethingThatMayBeNaN is NaN (or 0 or any other falsey value), x will be set to 0. If somethingThatMayBeNaN is truthy, x will be set to somethingThatMayBeNaN. When you're dealing with a numeric calculation, usually the only falsey values that you may have are 0 or NaN.
"Falsey" and "truthy": The "falsey" values are 0, "", NaN, undefined, null, and of course, false. Everything is is "truthy".
This will check if the value is NaN and then it assigns 0 to it.
anyNan = isNaN(anyNan) ? 0 : anyNan;
Assuming is golfStroke that could be NaN, for example:
var scoreStroke = parStroke - ~~golfStroke;
In that way any number would remains the same, and any "falsy" value – like NaN – would become 0.

What causes isNaN to malfunction? [duplicate]

This question already has answers here:
Validate decimal numbers in JavaScript - IsNumeric()
(52 answers)
Closed 9 years ago.
I'm simply trying to evaluate if an input is a number, and figured isNaN would be the best way to go. However, this causes unreliable results. For instance, using the following method:
function isNumerical(value) {
var isNum = !isNaN(value);
return isNum ? "<mark>numerical</mark>" : "not numerical";
}
on these values:
isNumerical(123)); // => numerical
isNumerical("123")); // => numerical
isNumerical(null)); // => numerical
isNumerical(false)); // => numerical
isNumerical(true)); // => numerical
isNumerical()); // => not numerical
shown in this fiddle: http://jsfiddle.net/4nm7r/1
Why doesn't isNaN always work for me?
isNaN returns true if the value passed is not a number(NaN)(or if it cannot be converted to a number, so, null, true and false will be converted to 0), otherwise it returns false. In your case, you have to remove the ! before the function call!
It is very easy to understand the behaviour of your script. isNaN simply checks if a value can be converted to an int. To do this, you have just to multiply or divide it by 1, or subtract or add 0. In your case, if you do, inside your function, alert(value * 1); you will see that all those passed values will be replaced by a number(0, 1, 123) except for undefined, whose numerical value is NaN.
You can't compare any value to NaN because it will never return false(even NaN === NaN), I think that's because NaN is dynamically generated... But I'm not sure.
Anyway you can fix your code by simply doing this:
function isNumerical(value) {
var isNum = !isNaN(value / 1); //this will force the conversion to NaN or a number
return isNum ? "<mark>numerical</mark>" : "not numerical";
}
Your ternary statement is backward, if !isNaN() returns true you want to say "numerical"
return isNum ? "not numerical" : "<mark>numerical</mark>";
should be:
return isNum ? "<mark>numerical</mark>" : "not numerical";
See updated fiddle:
http://jsfiddle.net/4nm7r/1/
Now that you already fixed the reversed logic pointed out on other answers, use parseFloat to get rid of the false positives for true, false and null:
var isNum = !isNaN(parseFloat(value));
Just keep in mind the following kinds of outputs from parseFloat:
parseFloat("200$"); // 200
parseFloat("200,100"); // 200
parseFloat("200 foo"); // 200
parseFloat("$200"); // NaN
(i.e, if the string starts with a number, parseFloat will extract the first numeric part it can find)
I suggest you use additional checks:
function isNumerical(value) {
var isNum = !isNaN(value) && value !== null && value !== undefined;
return isNum ? "<mark>numerical</mark>" : "not numerical";
}
If you would like treat strings like 123 like not numerical than you should add one more check:
var isNum = !isNaN(value) && value !== null && value !== undefined && (typeof value === 'number');

Inconsistency in javascript comparison operator [duplicate]

This question already has answers here:
Why does ('0' ? 'a' : 'b') behave different than ('0' == true ? 'a' : 'b') [duplicate]
(6 answers)
Closed 8 years ago.
Can anyone explain why here a = [] ? 1 : 2 a will be equal to 1 and here b = [] == true ? 1 : 2 b will be equal to 2
A very similar case is handled in Why does ('0' ? 'a' : 'b') behave different than ('0' == true ? 'a' : 'b').
In short:
When you have a single value that is evaluated in a boolean context, it is passed to ToBoolean to be converted to a boolean value.
If you compare values with == though, the algorithm in section 11.9.3 of the ECMAScript specification takes place. In this algorithm, both operands are converted to either strings or numbers and these values are compared.
More detailed explanation
a = [] ? 1 : 2
The condition is converted to a boolean by calling ToBoolean(GetValue(lref)). Now I assume that for objects, GetValue just returns the object itself and all objects evaluate to true.
Since arrays are just objects, the result of this expression is 1.
b = [] == true ? 1 : 2
As already said, quite some type conversion is going on here.
First, true is converted to a number:
7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
false is converted to 0 and true is converted to 1.
So we have
[] == 1
Then step 9 applies:
9. If Type(x) is Object and Type(y) is either String or Number,
return the result of the comparison ToPrimitive(x) == y.
That means [] is converted to a primitive value (string or number). If you follow the ToPrimitive function (and section 8.12.8), you'll find out that arrays are converted to strings, by concatenating their elements with ,. Since an empty array as no elements, the result is an empty string.
So we end up with
"" == 1
Then step 5 applies:
5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
An empty string is converted to 0, hence 0 == 1 is false and the conditional operator returns 2.
Because an array is an object, and when an object is evaluated in the context of a boolean comparison, it is "truthy", but not exactly true.
In the first example the array is being converted to a Boolean which yields true as it's not null, undefined, "", 0 or false.
In the second example you're getting a type conversion because of the equals operator. From mdn:
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible.
Tried the following in the console:
Number(true) //gives 1
Number([]) //gives 0
So when converted to numbers these are not equal.
In a = [] ? 1 : 2, it returns 1 if [] is not null or undefined.
In b = [] == true ? 1 : 2, it would return 1 if [] is true, but it's not, so it returns 2.
The first is an assignment and thus has to fall through to true (but DOESN'T equate anything). Equating empty to true will be false.
Because initialising an array with [] returns true and [] == true does not :-)

Categories

Resources