Why 'Null >= 0 && Null <= 0' But Not 'Null == 0'

Why `null = 0 && null = 0` but not `null == 0`?

Your real question seem to be:

Why:

null >= 0; // true

But:

null == 0; // false

What really happens is that the Greater-than-or-equal Operator (>=), performs type coercion (ToPrimitive), with a hint type of Number, actually all the relational operators have this behavior.

null is treated in a special way by the Equals Operator (==). In a brief, it only coerces to undefined:

null == null; // true
null == undefined; // true

Value such as false, '', '0', and [] are subject to numeric type coercion, all of them coerce to zero.

You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.

In Summary:

  • Relational Comparison: if both values are not type String, ToNumber is called on both. This is the same as adding a + in front, which for null coerces to 0.

  • Equality Comparison: only calls ToNumber on Strings, Numbers, and Booleans.

Why is null in JavaScript bigger than -1, less than 1, but not equal (==) to 0? What is it exactly then?

When you compare null for equality to 0, the result is false. If you force null to be interpreted in a numeric context then it is treated like 0 and the result becomes true.

You can force it to be numeric by putting + in front, or by using numeric operators like <, <=, >, and >=. Notice how null >= 0 and null <= 0 are both true.

> null == 0
false
> +null == 0
true
> null >= 0
true
> null <= 0
true

The ECMAScript Language Specification defines when a so-called "ToNumber" conversion is performed. When it is, null and false are both converted to 0.

§9.1 Type Conversion and Testing:


Table 14 — To Number Conversions


Argument Type Result
------------- ------
Undefined Return NaN
Null Return +0
Boolean Return 1 if argument is true. Return +0 if argument is false.
Number Return argument (no conversion).
String See grammar and note below.

Knowing when the ToNumber conversion is applied depends on the operator in question. For the relational operators <, <=, >, and >= see:

§11.8.5 The Abstract Relational Comparison Algorithm:


The comparison x < y, where x and y are values, produces true, false,
or undefined (which indicates that at least one operand is NaN). Such
a comparison is performed as follows:

  1. Call ToPrimitive(x, hint Number).

  2. Call ToPrimitive(y, hint Number).

  3. If Type(Result(1)) is String and Type(Result(2)) is String, go to step 16. (Note that this step differs from step 7 in the algorithm for
    the addition operator + in using and instead of or.)

  4. Call ToNumber(Result(1)).

  5. Call ToNumber(Result(2)).

The == operator is different. Its type conversions are described below. Notice how null and false follow different rules.

§11.9.3 The Abstract Equality Comparison Algorithm


The comparison x == y, where x and y are values, produces true or
false. Such a comparison is performed as follows:

1. If Type(x) is different from Type(y), go to step 14.

...

14. If x is null and y is undefined, return true.

15. If x is undefined and y is null, return true.

16. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).

17. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

18. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.

19. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

20. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).

21. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

22. Return false.

If you read carefully you can see why false == 0 is true but null == 0 is false.

  • For false == 0, Type(x) is Boolean. This means Step 18's type conversion is applied, and false is converted to a number. ToNumber(false) is 0, and 0 == 0 is true, so the comparison succeeds.

  • For null == 0, Type(x) is Null. None of the type checks match so the comparison falls through to Step 22, which returns false. The comparison fails.

Javascript comparison question (null = 0)

The relational operators (>= and <=), perform type coercion (ToPrimitive), with a hint type of Number, all the relational operators present have this behavior.

You can see the inner details of this process in the The Abstract Relational Comparison Algorithm.

On the other hand, the Equals operator (==), if an operand is null it only returns true if the other is either null or undefined, no numeric type coercion is made.

null == undefined; // true
null == null; // true

Check the inner details of this process in the The Abstract Relational Comparison Algorithm.

Recommended articles:

  • typeof, == and ===
  • Notes on ECMAScript Equality Operators

How do I check for null values in JavaScript?

JavaScript is very flexible with regards to checking for "null" values. I'm guessing you're actually looking for empty strings, in which case this simpler code will work:

if(!pass || !cpass || !email || !cemail || !user){

Which will check for empty strings (""), null, undefined, false and the numbers 0 and NaN.

Please note that if you are specifically checking for numbers, it is a common mistake to miss 0 with this method, and num !== 0 is preferred (or num !== -1 or ~num (hacky code that also checks against -1)) for functions that return -1, e.g. indexOf).

Handle null = 0 in Typescript

You can employ a type guard that will assure the compiler that you're not handling a null but a number. Moreover, it will make the code more correct, since with value: any this means you might get a boolean or a string passed in:

public print(value: any): void {
if (typeof value === "number") {
//value is definitely a number and not null
if (value >= 0) {
console.log('Greater than zero')
}
}
}

Playground Link

Now the code specifically verifies that you do get a number and then checks if it's more than or equal to zero. This means that a null or a non-number value would not be processed.

The type guard condition can be combined with the other for brevity:

public print(value: any): void {
if (typeof value === "number" && value >= 0) {
console.log('Greater than zero')
}
}

Playground Link

Or extracted on its own to just reduce the nesting:

public print(value: any): void {
if (typeof value !== "number")
return;

//value is definitely a number and not null
if (value >= 0) {
console.log('Greater than zero')
}
}

Playground Link

What is the difference between NULL, '\0' and 0?

Note: This answer applies to the C language, not C++.



Null Pointers

The integer constant literal 0 has different meanings depending upon the context in which it's used. In all cases, it is still an integer constant with the value 0, it is just described in different ways.

If a pointer is being compared to the constant literal 0, then this is a check to see if the pointer is a null pointer. This 0 is then referred to as a null pointer constant. The C standard defines that 0 cast to the type void * is both a null pointer and a null pointer constant.

Additionally, to help readability, the macro NULL is provided in the header file stddef.h. Depending upon your compiler it might be possible to #undef NULL and redefine it to something wacky.

Therefore, here are some valid ways to check for a null pointer:

if (pointer == NULL)

NULL is defined to compare equal to a null pointer. It is implementation defined what the actual definition of NULL is, as long as it is a valid null pointer constant.

if (pointer == 0)

0 is another representation of the null pointer constant.

if (!pointer)

This if statement implicitly checks "is not 0", so we reverse that to mean "is 0".

The following are INVALID ways to check for a null pointer:

int mynull = 0;
<some code>
if (pointer == mynull)

To the compiler this is not a check for a null pointer, but an equality check on two variables. This might work if mynull never changes in the code and the compiler optimizations constant fold the 0 into the if statement, but this is not guaranteed and the compiler has to produce at least one diagnostic message (warning or error) according to the C Standard.

Note that the value of a null pointer in the C language does not matter on the underlying architecture. If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.

As such, even on this funny architecture, the following ways are still valid ways to check for a null pointer:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

The following are INVALID ways to check for a null pointer:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

as these are seen by a compiler as normal comparisons.

Null Characters

'\0' is defined to be a null character - that is a character with all bits set to zero. '\0' is (like all character literals) an integer constant, in this case with the value zero. So '\0' is completely equivalent to an unadorned 0 integer constant - the only difference is in the intent that it conveys to a human reader ("I'm using this as a null character.").

'\0' has nothing to do with pointers. However, you may see something similar to this code:

if (!*char_pointer)

checks if the char pointer is pointing at a null character.

if (*char_pointer)

checks if the char pointer is pointing at a non-null character.

Don't get these confused with null pointers. Just because the bit representation is the same, and this allows for some convenient cross over cases, they are not really the same thing.

References

See Question 5.3 of the comp.lang.c FAQ for more.
See this pdf for the C standard. Check out sections 6.3.2.3 Pointers, paragraph 3.



Related Topics



Leave a reply



Submit