I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);
Related
I want to check whether the value in an input box is equal to a variable. When I use ===, it returns false but when I use ==, it returns true, provided both are equal.
<input id="g1"></input> <button id="b" onclick="myFunction()">Try</button>
function myFunction() {
var d1;
d1 = Math.floor(Math.random()*100)
if( document.getElementById("g1").value == d1) {
document.getElementById("d").innerHTML = "Correct";
}
This happens because JavaScript == can compare numeric strings to numbers whereas === does not.
Similarly the "value" property your using returns a string that you're comparing to an integer. You'll need to use parseInt to convert the value first.
parseInt(document.getElementById("g1").value) === d1
A few things to consider with parseInt:
parseInt returns NaN when you try to convert non-number strings (i.e. converting 'bogus' returns NaN.
It will convert decimals into integers by dropping the decimals. So parseInt('2.1') == 2 // => true.
Honestly, given your use case, it's appropriate to use ==, but I'd add a comment explaining why it's being used.
=== means both value has to be equals but have same type of data in it aswell where == means they only needs to be equal. so for example if d1 is a string holding value 2 and g1 is an integer also holding value 2 using === would not work and will return false as both data is different even though they have same syntax.
<input id="g1"></input> <button id="b" onclick="myFunction()">Try</button>
function myFunction() {
var d1 = 0;
d1 = Math.floor(Math.random()*100)
if( paseint(document.getElementById("g1").value) === d1) {
document.getElementById("d").innerHTML = "Correct";
}
== is the equality operator
=== is an identity operator
For example true==1 is true because true is converted to 1 and then it's compared. However, true===1 is false. This is because it does not do type coercion.
That aside, in your case I think you want to try casting your value to an integer and then compare.
var string5 = '5'
var numb5 = 5
if (string5 == numb5) will return true
if (string5 === numb5) will return false
second variant also compares type, because string is not same type as number it is false.
1) Why the 155100 is a number here? Just like 255 would be if var s = 155;.
2) Why the 155100 is still a number even if var n = "100"; ?
3) Where and why is var res converted to a number?
What am I missing here?
var s = "155";
var n = 100;
var res = s + n;
document.write(res + "<hr>");
if ( isNaN(res) ) {
document.write("It is not a number");
}
if ( !isNaN(res) ) {
document.write("It is a number");
}
<html>
<head>
<title>stackoverflow.com</title>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
Thank you so much!
To your questions:
Why the 155100 is a number here? Just like 255 would be if var s = 155;?
It is a string, but when passed to isNaN, that function coerces it to a number and then returns whether that coercion resulted in NaN.
Why the 155100 is still a number even if var n = "100";?
See above. It is not.
Where and why is var res converted to a number?
It is not -- it remains a string.
But as documented on MDN:
When the argument to the isNaN function is not of type Number, the value is first coerced to a Number.
Notes
To check if a variable is of the Number type:
if (typeof res === 'number')
To convert a string to a number, one of these:
i = +res;
i = Number(res);
If you want to only check the start of a string, and not fail if any subsequent characters are not numeric (like 123.45abc), then use:
i = parseFloat(res);
If your interest is only in integers, you can use parseInt, preferably with the second argument to indicate the base. Like with parseFloat, it does not return NaN as soon as the first character passes the test:
i = parseInt(res, 10);
See the MDN link here.
isNaN(res) ---> will be false because 155100 is numeric
typeof res ---> string
Go ahead - try it in your Chrome console right now.
typeof "155100"
isNaN will always return false for a string value regardless of whether or not it can be parsed into a valid number. In order to check if your string is a valid number, you can parse it with parseInt and check if the result is NaN:
var s = "155";
var n = 100;
var res = s + n;
document.write(res + "<hr>");
if ( isNaN(parseInt(res)) ) {
document.write("It is not a number");
} else {
document.write("It is a number");
}
Note: parseInt will only return NaN if the first character cannot be converted to a number. MDN has a "stricter" version here that returns NaN if any part of the string cannot be converted .
JavaScript is a language based upon loose type-interpretation, instead of implicitly requiring type declaration or throwing an error else-wise;
When JavaScript gets a something in quotes, it determines it to be a string; the + operator, with the type now being String, is understood by JavaScript in this context as a string concatenater (concatenation is the combination of two or more things things) and so it happily appends the two together.
Here, you need to do what is known as Type Casting or Type Throwing where you throw(or cast) something into a different type. This is necessary here so that your + operator will behave as you desire
For Example:
var str = "3.14";
var num = new Number(str);
The new keyword is optional, but is recommended for source clarity and readability.
I am able to compare version numbers correctly in JavaScript without having to split and check each decimal numbers. How is it working?
("2.0.1" > "2.1.0")
false
("2.2.1" > "2.1.0")
true
("2.5.1" > "2.0.5")
true
Thanks.
No, you're not " able to compare version numbers correctly in JavaScript without having to split"
"2.2.8" > "2.2.10" // true
Those strings are compared character after character, from left to right.
You do need to split and compare number after number, which is easy enough. Here's for example how you could implement it:
function Version(s){
this.arr = s.split('.').map(Number);
}
Version.prototype.compareTo = function(v){
for (var i=0; ;i++) {
if (i>=v.arr.length) return i>=this.arr.length ? 0 : 1;
if (i>=this.arr.length) return -1;
var diff = this.arr[i]-v.arr[i]
if (diff) return diff>0 ? 1 : -1;
}
}
console.log((new Version("1.1.1")).compareTo(new Version("1.2.1"))); // -1
console.log((new Version("1.1.1")).compareTo(new Version("1.10.1"))); // -1
console.log((new Version("1.10.1.2")).compareTo(new Version("1.10.1"))); // 1
console.log((new Version("1.10.1.2")).compareTo(new Version("1.10.1.2"))); // 0
Because you're comparing strings lexicographically, which yields the same result in your examples. However, this won't work in all circumstances, like when you get into double digits: 2.15.29.
I know this is old and already have a marked answer, but the below code works pretty well for me using localeCompare.
The function will return either:
0: the version strings are equal
1: the version a is greater than b
-1: the version b is greater than a
function sort(a, b){
return a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' })
}
The above works for angularJS and Javascript. The localeCompare() is an ES1 feature that is supported by all browsers.
For more detail on the usage refer to - https://www.w3schools.com/jsref/jsref_localecompare.asp
better way to compare is to create a version number float and then a sub version number, like shown below
subVersion = parseInt(fullVersion.split(".")[2]);
mainVersion = parseFloat(fullOsVer);
after this conversion, you can do comparison. this comparison will be comparing two integers.
I have a list of string 'X1','X2','X3','S1','S2','S3',etc. I want to do the following comparison
var string = INPUT STRING;
if( string > 'X10' ){
DO THIS
}else{
DO THAT
}
In this case, if the input string is 'X8' then my code is returning X8 IS GREATER than X10. If there a way I can truly get X10 > X8?
You can split it into alphabetical and numeric parts. Assuming the alphabetical part is only one character,
var alpha = string.charAt(0);
var num = string.substring(1) | 0; // | 0 to cast to integer
if (alpha > 'X' && num > 10) {
…
If you're looking out for a natural sorting or comparison of alphanumeric strings, you can try using the localeCompare() method.
It outputs a -1, 0 or 1 for results which are less than, equal or greater than respectively. It has some interesting options to provide as well. For instance, to get a natural alphanumeric sort (x10 < x8), you may pass the numeric: true option. To also make the case insensitive while comparing the string, you may also pass sensitivity: 'base' option. This would compare the two strings value and VALUE as equal, ignoring the casings.
An example using both the options is below:
leftString.localeCompare(rightString, undefined, { numeric: true, sensitivity: 'base'})
// With this you would get following results
// X8 < X10
// X8 === x8
Hope this is useful. Cheers!
I need to compare two Integers which could exceed Integer range limit. How do I get this in javascript.
Initially, I get the value as String, do a parseInt and compare them.
var test = document.getElementById("test").value;
var actual = document.getElementById("actual").value;
if ( parseInt(test) == parseInt(actual)){
return false;
}
Any options to use long ? Also, which is best to use parseInt or valueOf ??
Any suggestions appreciated,
Thanks
You'd better to assign the radix. Ex. parseInt('08') will give 0 not 8.
if (parseInt(test, 10) === parseInt(actual, 10)) {
Leave them in String and compare (after you have cleaned up the string of leading and trailing spaces, and other characters that you consider safe to remove without changing the meaning of the number).
The numbers in Javascript can go up to 53-bit precision. Check whether your number is within range.
Since the input is expected to be integer, you can be strict and only allow the input to only match the regex:
/\s*0*([1-9]\d*|0)\s*/
(Arbitrary leading spaces, arbitrary number of leading 0's, sequence of meaningful digits or single 0, arbitrary trailing spaces)
The number can be extract from the first capturing group.
Assuming integers and that you've already validated for non-numeric characters that you don't want to be part of the comparison, you can clean up some leading/trailing stuff and then just compare lengths and if lengths are equal, then do a plain ascii comparison and this will work for any arbitrary length of number:
function mTrim(val) {
var temp = val.replace(/^[\s0]+/, "").replace(/\s+$/, "");
if (!temp) {
temp = "0";
}
return(temp);
}
var test = mTrim(document.getElementById("test").value);
var actual = mTrim(document.getElementById("actual").value);
if (test.length > actual.length) {
// test is greater than actual
} else if (test.length < actual.length) {
// test is less than actual
} else {
// do a plain ascii comparison of test and actual
if (test == actual) {
// values are the same
} else if (test > ascii) {
// test is greater than actual
} else {
// test is less than actual
}
}