Why NaN is greater than any number in JavaScript? [duplicate] - javascript

This question already has answers here:
What is the rationale for all comparisons returning false for IEEE754 NaN values?
(12 answers)
Closed 8 years ago.
Here is an example:
parseInt(50) > parseInt('a');
When executing this on a console, it will return false. My original code looks somewhat like this:
variableB = parseInt(jQuery('some-element').html());
if(parseInt(variableA) > variableB)
// do something
else
// do something else
Sometimes the some-element will not be filled and thus return NaN. When this happens, I do want the else block to be executed. I am actually getting what I expect, but I just want to make sure that it indeed is intended to work this way.

In IEEE 754 arithmethic, the floating-point model used by JavaScript, NaN (or not-a-number) is, by definition, not less than, equal to, or greater than any other number.
Notice that this even applies to two NaNs: if x = NaN and y = NaN, the comparison x === y will return false.
Below I quote the portion of the IEEE 754 Standard (Section 5.11) where this behavior is specified:
Four mutually exclusive relations are possible: less than, equal,
greater than, and unordered. The last case arises when at least one
operand is NaN. Every NaN shall compare unordered with
everything, including itself.

All comparisons involving NaN will always return false.
NaN is neither less than nor greater than any number.

Related

Why does Math.min() return -0 from [+0, 0, -0]

I know (-0 === 0) comes out to be true. I am curious to know why -0 < 0 happens?
When I run this code in stackoverflow execution context, it returns 0.
const arr = [+0, 0, -0];
console.log(Math.min(...arr));
But when I run the same code in the browser console, it returns -0. Why is that? I have tried to search it on google but didn't find anything useful. This question might not add value to someone practical example, I wanted to understand how does JS calculates it.
const arr = [+0, 0, -0];
console.log(Math.min(...arr)); // -0
-0 is not less than 0 or +0, both -0 < 0 and -0 < +0 returns False, you're mixing the behavior of Math.min with the comparison of -0 with 0/+0.
The specification of Math.min is clear on this point:
b. If number is -0𝔽 and lowest is +0𝔽, set lowest to -0𝔽.
Without this exception, the behavior of Math.min and Math.max would depend on the order of arguments, which can be considered an odd behavior — you probably want Math.min(x, y) to always equal Math.min(y, x) — so that might be one possible justification.
Note: This exception was already present in the 1997 specification for Math.min(x, y), so that's not something that was added later on.
This is a specialty of Math.min, as specified:
21.3.2.25 Math.min ( ...args )
[...]
For each element number of coerced, do
a. If number is NaN, return NaN.
b. If number is -0𝔽 and lowest is +0𝔽, set lowest to -0𝔽.
c. If number < lowest, set lowest to number.
Return lowest.
Note that in most cases, +0 and -0 are treated equally, also in the ToString conversion, thus (-0).toString() evaluates to "0". That you can observe the difference in the browser console is an implementation detail of the browser.
The point of this answer is to explain why the language design choice of having Math.min be fully commutative makes sense.
I am curious to know why -0 < 0 happens?
It doesn't really; < is a separate operation from "minimum", and Math.min isn't based solely on IEEE < comparison like b<a ? b : a.
That would be non-commutative wrt. NaN as well as signed-zero. (< is false if either operand is NaN, so that would produce a).
As far as principle of least surprise, it would be at least as surprising (if not moreso) if Math.min(-1,NaN) was NaN but Math.min(NaN, -1) was -1.
The JS language designers wanted Math.min to be NaN-propagating, so basing it just on < wasn't possible anyway. They chose to make it fully commutative including for signed zero, which seems like a sensible decision.
OTOH, most code doesn't care about signed zero, so this language design choice costs a bit of performance for everyone to cater to the rare cases where someone wants well-defined signed-zero semantics.
If you want a simple operation that ignores NaN in an array, iterate yourself with current_min = x < current_min ? x : current_min. That will ignore all NaN, and also ignore -0 for current_min <= +0.0 (IEEE comparison). Or if current_min starts out NaN, it will stay NaN. Many of those things are undesirable for a Math.min function, so it doesn't work that way.
If you compare other languages, the C standard fmin function is commutative wrt. NaN (returning the non-NaN if there is one, opposite of JS), but is not required to be commutative wrt. signed zero. Some C implementations choose to work like JS for +-0.0 for fmin / fmax.
But C++ std::min is defined purely in terms of a < operation, so it does work that way. (It's intended to work generically, including on non-numeric types like strings; unlike std::fmin it doesn't have any FP-specific rules.) See What is the instruction that gives branchless FP min and max on x86? re: x86's minps instruction and C++ std::min which are both non-commutative wrt. NaN and signed zero.
IEEE 754 < doesn't give you a total order over distinct FP numbers. Math.min does except for NaNs (e.g. if you built a sorting network with it and Math.max.) Its order disagrees with Math.max: they both return NaN if there is one, so a sorting network using min/max comparators would produce all NaNs if there were any in the input array.
Math.min alone wouldn't be sufficient for sorting without something like == to see which arg it returned, but that breaks down for signed zero as well as NaN.
The spec is curiously contradictory. The < comparison rule explicitly says that -0 is not less than +0. However, the spec for Math.min() says the opposite: if the current (while iterating through the arguments) value is -0, and the smallest value so far is +0, then the smallest value should be set to -0.
I would like for somebody to activate the T.J. Crowder signal for this one.
edit — it was suggested in some comments that a possible reason for the behavior is to make it possible to detect a -0 value, even though for almost all purposes in normal expressions the -0 is treated as being plain 0.

What exactly does isNaN() do in javaScript? [duplicate]

This question already has answers here:
Is Number.IsNaN() more broken than isNaN()
(11 answers)
Closed 7 years ago.
isNaN() returns false if and only if the argument is number.
var a = new Number(1);
By doing so, a is an object now.
So why is isNaN(a) returning false?
isNaN() tests whether an input is NOT a number.
var a = new Number(1)
a is a number object. Therefore isNaN() returns false.
Here is a nice documentation containing isNaN() behaviors with different edge cases. Unfortunately some of them are not as intuitive as hoped, so it's worth reading.
The global isNaN() function coerces its argument to a number value before testing for NaN. Your object converts cleanly to the number 1, and 1 is not NaN.
Note that isNaN("1") also returns false, because the string "1" converts cleanly to a number that isn't NaN.
The isNaN function is not really intended as a general-purpose test for whether something is or is not a number. It's a test for the specific numeric value NaN. It's often used as a general-purpose test, and that (mostly) works because JavaScript returns NaN when an attempt to convert a value to a number fails. That's somewhat impure, because NaN exists as a marker with a specific purpose in the floating point system.
Some JavaScript environments have Number.isNaN() in addition to the global isNaN. The function on the Number constructor does not perform a type coercion first. For that reason, Number.isNaN("foo") returns false, because even though the string "foo" cannot be converted to a number cleanly, it's not the constant NaN.

Comparing NaN in javascript [duplicate]

This question already has answers here:
How do I test for NaN? [duplicate]
(2 answers)
Closed 7 years ago.
In Javascript, if we multiply a string with number we get NaN:
console.log("manas" * 5); // result is NaN
Why then does the following code result in false instead of true?
console.log("manas" * 5 == NaN) // results false
Use the isNaN function instead.
console.log(isNaN("manas" * 5));
http://www.w3schools.com/jsref/jsref_isnan.asp
NaN, not a number, is a special type value used to denote an unrepresentable value. With JavaScript, NaN can cause some confusion, starting from its typeof and all to the way the comparison is handled.
Several operations can lead to NaN as the result.
Because there are many ways to represent a NaN, it makes sense that one NaN will not be equal to another NaN.
NaN is a special numeric value which is not equal to anything including itself. To properly test for NaN you need to use isNaN function.
From specification:
Returns true if the argument coerces to NaN, and otherwise returns false.
Here is also useful note from the same ECMAScript section:
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.
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.
Testing against NaN
In Javascript,
NaN == NaN //always results false.
(self comparison of NaN to itself is always false in javascript)
refer:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN
also see Is NaN equal to NaN?
Javascript is not that smart - when either side of the == operator is Nan, the whole thing evaluates as false (similar to how if leftside of || is false, it doesn't bother looking at right side)
So, even Nan == Nan will return false.
Here's a good article on Nan behaviour
http://ariya.ofilabs.com/2014/05/the-curious-case-of-javascript-nan.html

Why eval("475957E-8905") == "475957E-8905" is true?

I made a program with nodeJs which generate code such as
eval("XXXXXX") == "XXXXXX"
It's working pretty well, but at a moment he gave me this :
eval("475957E-8905") == "475957E-8905"
I tested it with Firebug, and the result is true
.But I don't really understand why.
Of course, eval("475957E-8905") return 0
but why 0 == "475957E-8905" ?
There are two pieces to this puzzle: floating-point numbers and type-insensitive comparison using ==.
First, 475957E-8905 evaluates as the floating point number 475957 * 10 ^ -8905, which is incredibly small; in floating-point terms, it's the same as 0 due to the precision limitations of javascript. So, eval("475957E-8905") returns 0.
Now, for the second piece of the puzzle.
The == means that the types don't have to match, so nodejs (like any JavaScript engine) tries to convert one of them so it can compare them.
Since eval("475957E-8905") returned 0, it tries to convert "475957E-8905" to an integer as well. As we have seen, that is also 0. Thus, the comparison is 0 == 0, which is true.
Note that the same thing happens if you do eval("3") == "3" or eval("3") == 3 -- in each case, the strings are converted to numbers and compared.
Avoiding this problem
You can force a type-sensitive comparison like this:
eval("475957E-8905") === "475957E-8905"
which returns false, because the === tells the javascript engine to return true only if the types and the values both match.
Javascript has to convert your string, "475957E-8905", to a number in order to compare them. When it does that, it converts "475957E-8905" to 0 as well. So, 0 == 0;
As you can see:
"475957E-8905" == 0
Is true. Basically you eval statement "475957E-8905" into a number, and then the other "475957E-8905" is being converted to a number for comparison. In the end, the exact same conversion process has happened to both of them and they are both 0.
use === to compare the type as well, for further information:
JavaScript has both strict and
type-converting equality comparison.
For strict equality the objects being
compared must have the same type and:
Two strings are strictly equal when they have the same sequence of
characters, same length, and same
characters in corresponding positions.
Two numbers are strictly equal when they are numerically equal (have
the same number value). NaN is not
equal to anything, including NaN.
Positive and negative zeros are equal
to one another.
Two Boolean operands are strictly equal if both are true or
both are false.
Two objects are strictly equal if they refer to the same Object.
Null and Undefined types are == (but not ===). [I.e. Null==Undefined (but not Null===Undefined)]
check this documentation

Why is NaN === NaN false? [duplicate]

This question already has answers here:
What is the rationale for all comparisons returning false for IEEE754 NaN values?
(12 answers)
Closed 6 years ago.
Why does NaN === NaN return false in Javascript?
> undefined === undefined
true
> NaN === NaN
false
> a = NaN
NaN
> a === a
false
On the documentation page I see this:
Testing against NaN
Equality operator (== and ===) cannot be used to test a value against NaN. Use isNaN instead.
Is there any reference that answers to the question? It would be welcome.
Strict answer: Because the JS spec says so:
If Type(x) is Number, then
If x is NaN, return false.
If y is NaN, return false.
Useful answer: The IEEE 754 spec for floating-point numbers (which is used by all languages for floating-point) says that NaNs are never equal.
This behaviour is specified by the IEEE-754 standard (which the JavaScript spec follows in this respect).
For an extended discussion, see What is the rationale for all comparisons returning false for IEEE754 NaN values?
Although either side of NaN===NaN contains the same value and their type is Number but they are not same. According to ECMA-262, either side of == or === contains NaN then it will result false value.
you may find a details rules in here-
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

Categories

Resources