Why does string to number comparison work in Javascript
Because JavaScript defines >=
and <=
(and several other operators) in a way that allows them to coerce their operands to different types. It's just part of the definition of the operator.
In the case of <
, >
, <=
, and >=
, the gory details are laid out in §11.8.5 of the specification. The short version is: If both operands are strings (after having been coerced from objects, if necessary), it does a string comparison. Otherwise, it coerces the operands to numbers and does a numeric comparison.
Consequently, you get fun results, like that "90" > "100"
(both are strings, it's a string comparison) but "90" < 100
(one of them is a number, it's a numeric comparison). :-)
Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
That's a matter of opinion. Some people think it's totally fine to rely on the implicit coercion; others think it isn't. There are some objective arguments. For instance, suppose you relied on implicit conversion and it was fine because you had those numeric constants, but later you were comparing x
to another value you got from an input field. Now you're comparing strings, but the code looks the same. But again, it's a matter of opinion and you should make your own choice.
If you do decide to explicitly convert to numbers first, parseInt
may or may not be what you want, and it doesn't do the same thing as the implicit conversion. Here's a rundown of options:
parseInt(str[, radix])
- Converts as much of the beginning of the string as it can into a whole (integer) number, ignoring extra characters at the end. SoparseInt("10x")
is10
; thex
is ignored. Supports an optional radix (number base) argument, soparseInt("15", 16)
is21
(15
in hex). If there's no radix, assumes decimal unless the string starts with0x
(or0X
), in which case it skips those and assumes hex. Does not look for the new0b
(binary) or0o
(new style octal) prefixes; both of those parse as0
. (Some browsers used to treat strings starting with0
as octal; that behavior was never specified, and was [specifically disallowed][2] in the ES5 specification.) ReturnsNaN
if no parseable digits are found.Number.parseInt(str[, radix])
- Exactly the same function asparseInt
above. (Literally,Number.parseInt === parseInt
istrue
.)parseFloat(str)
- LikeparseInt
, but does floating-point numbers and only supports decimal. Again extra characters on the string are ignored, soparseFloat("10.5x")
is10.5
(thex
is ignored). As only decimal is supported,parseFloat("0x15")
is0
(because parsing ends at thex
). ReturnsNaN
if no parseable digits are found.Number.parseFloat(str)
- Exactly the same function asparseFloat
above.Unary
+
, e.g.+str
- (E.g., implicit conversion) Converts the entire string to a number using floating point and JavaScript's standard number notation (just digits and a decimal point = decimal;0x
prefix = hex;0b
= binary [ES2015+];0o
prefix = octal [ES2015+]; some implementations extend it to treat a leading0
as octal, but not in strict mode).+"10x"
isNaN
because thex
is not ignored.+"10"
is10
,+"10.5"
is10.5
,+"0x15"
is21
,+"0o10"
is8
[ES2015+],+"0b101"
is5
[ES2015+]. Has a gotcha:+""
is0
, notNaN
as you might expect.Number(str)
- Exactly like implicit conversion (e.g., like the unary+
above), but slower on some implementations. (Not that it's likely to matter.)Bitwise OR with zero, e.g.
str|0
- Implicit conversion, like+str
, but then it also converts the number to a 32-bit integer (and convertsNaN
to0
if the string cannot be converted to a valid number).
So if it's okay that extra bits on the string are ignored, parseInt
or parseFloat
are fine. parseInt
is quite handy for specifying radix. Unary +
is useful for ensuring the entire string is considered. Takes your choice. :-)
For what it's worth, I tend to use this function:
const parseNumber = (str) => str ? +str : NaN;
(Or a variant that trims whitespace.) Note how it handles the issue with +""
being 0
.
And finally: If you're converting to number and want to know whether the result is NaN
, you might be tempted to do if (convertedValue === NaN)
. But that won't work, because as Rick points out below, comparisons involving NaN
are always false. Instead, it's if (isNaN(convertedValue))
.
Javascript compare numbers as strings
If you want to compare them without converting them to numbers, you can set numeric: true
in the options
parameter
console.log( "116457".localeCompare("3085", undefined, { numeric: true }))console.log( "116457".localeCompare("3085"))
Comparing String with Integer in javascript
When the runtime attempts to convert 'sachin'
to a number, it will fail and end up as NaN
. That special constant results in false
for any comparison to any other numeric value. The NaN
constant ("Not A Number") is not equal to any other value, nor is it less than or greater than any other value.
edit — the ==
, <
, and >
operators all "prefer" numbers to strings. If one operand is a number and the other a string, they'll always try to interpret the string as a number. It doesn't matter what order the operands appear in; what matters is the operand types.
(Strictly speaking, the results of <
and >
when NaN
is involved are supposed to be undefined
, according to the spec, but Firefox seems to give false
instead.)
How to compare two string values as integers?
Use this :
if(parseInt(x, 10)!=parseInt(y, 10))
If you don't precise the radix, "09" is parsed as octal (this gives 0).
MDN documentation about parseInt
Note that you shouldn't even rely on this interpretation when working with octal representations :
ECMAScript 5 Removes Octal Interpretation
The ECMAScript 5 specification of the function parseInt no longer
allows implementations to treat Strings beginning with a 0 character
as octal values. ECMAScript 5 states:The parseInt function produces an integer value dictated by
interpretation of the contents of the string argument according to the
specified radix. Leading white space in string is ignored. If radix is
undefined or 0, it is assumed to be 10 except when the number begins
with the character pairs 0x or 0X, in which case a radix of 16 is
assumed. If radix is 16, number may also optionally begin with the
character pairs 0x or 0X.This differs from ECMAScript 3, which discouraged but allowed octal
interpretation.Since many implementations have not adopted this behavior as of 2011,
and because older browsers must be supported, always specify a radix.
Simply :
always specify a radix
comparing 2 numers in javascript with parseint
You should validate
the number1 and number2 before compare, or set type="number"
for inputs
Example parseInt("1a")
return 1
If you input 1a and 1, it show equal.
Is JavaScript string comparison just as fast as number comparison?
String comparison could be "just as fast" (depending on implementation and values) - or it could be "much slower".
The ECMAScript specification describes the semantics, not the implementation. The only way to Know for Certain is to create an applicable performance benchmark on run it on a particular implementation.
Trivially, and I expect this is the case1, the effects of string interning for a particular implementation are being observed.
That is, all string values (not String Objects) from literals can be trivially interned into a pool such that implIdentityEq("foo", "foo")
is true - that is, there need only one string object. Such interning can be done after constant folding, such that "f" + "oo" -> "foo"
- again, per a particular implementation as long as it upholds the ECMAScript semantics.
If such interning is done, then for implStringEq
the first check could be to evaluate implIdentityEq(x,y)
and, if true, the comparison is trivially-true and performed in O(1). If false, then a normal string character-wise comparison would need to be done which is O(min(n,m)).
(Immediate falseness can also be determined with x.length != y.length
, but that seems less relevant here.)
1 While in the above I argue for string interning being a likely cause, modern JavaScript implementations perform a lot of optimizations - as such, interning is only a small part of the various optimizations and code hoistings that can (and are) done!
I've created an "intern breaker" jsperf. The numbers agree with the hypothesis presented above.
If a string is interned then comparison is approximate in performance to testing for "identity" - while it is slower than a numeric comparison, this is still much faster than a character-by-character string comparison.
Holding the above assertion, IE10 does not appear to consider object-identity for pass-fast string comparisons although it does use a fast-fail length check.
In Chrome and Firefox, two intern'ed strings which are not equal are also compared as quickly as two that are - there is likely a special case for comparing between two different interned strings.
Even for small strings (length = 8), interning can be much faster. IE10 again shows it doesn't have this "optimization" even though it appears to have an efficient string comparison implementation.
The string comparison can fail as soon as the first different character is encountered: even comparing long strings of equal length might only compare the first few characters.
Do common JavaScript implementations use string interning? (but no references given)
Yes. In general any literal string, identifier, or other constant string in JS source is interned. However implementation details (exactly what is interned for instance) varies, as well as when the interning occurs
See JS_InternString (FF does have string interning, although where/how the strings are implicitly interened from JavaScript, I know not)
comparison operator false
Because you are comparing strings, not numbers.
It compares each character in the same position from the left. So '1' is lower than '2' in character set, it stops comparing and returns false
.
console.log('1000' > '200')// falseconsole.log(1000 > 200)// true
Related Topics
How to Get the Pure Text Without HTML Element Using JavaScript
Passing Variable Through JavaScript from One HTML Page to Another Page
How to Disable All Div Content
How to Force a Script Reload and Re-Execute
How to Create a New Line in JavaScript
Disable Interpolation When Scaling a ≪Canvas≫
How to Store an Array in Localstorage
How to Validate Inputs Dynamically Created Using Ng-Repeat, Ng-Show (Angular)
Jsfiddle Code Not Working in My Own Page
Do You Need Text/JavaScript Specified in Your ≪Script≫ Tags
How to Get Selected Text from a Textbox Control With JavaScript
How to Store Arbitrary Data For Some HTML Tags
Get Page Generated With JavaScript in Python
How to Remove an HTML Element Using JavaScript
Which Browsers Support ≪Script Async="Async" /≫