This question already has answers here:
Why does JavaScript handle the plus and minus operators between strings and numbers differently?
(7 answers)
Closed 6 years ago.
The following code gives weird results:
console.log("" + 1 + 10 + 2 - 5 + "8");
I've tried inputting various different values to work it out but I cannot understand what's going on under the hood.
"" + 1 === "1"
"1" + 10 === "110"
"110" + 2 === "1102"
"1102" - 5 === 1097
1097 + "8" === "10978"
In JavaScript, the + operator is used for both numeric addition and string concatenation. When you "add" a number to a string the interpreter converts your number to a string and concatenates both together.
When you use the - operator, however, the string is converted back into a number so that numeric subtraction may occur.
When you then "add" a string "8", string concatenation occurs again. The number 1097 is converted into the string "1097", and then joined with "8".
string + number = concatenated string
number + number = the sum of both numbers
string - number = the difference between (coerced string) and the number
explanation:
If one or both operands is string, then the plus is considered as string concatenation operator rather than adding numbers.
the minus operator always try to convert both operands to numbers.
so:
"" + 1 + 10 + 2 = (string) "1102"
"1102" - 5 = (number) 1097
1097 + "8" = (string) "10798"
This is a string not a number--""
This is a string not a number--"1"
This is a string not a number--"1" <+> "10" = "1"+"10" = "110"'
This is a string not a number--"1" <+> "10" <+> "2" = "1"+"10"+"2" = "1102"
This is a number because there's no confusion about a minus operator--1102 - 5 = 1097
This is a string not a number--"1097" <+> "8" = "1097"+"8" = "10978"
SNIPPET
document.getElementById("1").innerHTML = "";
document.getElementById("2").innerHTML = "" + 1;
document.getElementById("3").innerHTML = "" + 1 + 10;
document.getElementById("4").innerHTML = "" + 1 + 10 + 2
document.getElementById("5").innerHTML = "" + 1 + 10 + 2 - 5
document.getElementById("6").innerHTML = "" + 1 + 10 + 2 - 5 + "8";
<ol>
<li id='1'></li>
<li id='2'></li>
<li id='3'></li>
<li id='4'></li>
<li id='5'></li>
<li id='6'></li>
</ol>
This site has some useful info.
JavaScript is very relaxed about the difference between strings and numbers.
...
So if you use + on a string and a number, JavaScript is going to make
the number a string for you. Better still, if you need it you can
treat numbers as strings or strings as numbers.
Conversely, if you apply mathematics to a string, JavaScript tries to
make it a number. If the string cannot be interpreted as a number
(because there are letters in it, for instance), JavaScript gives NaN
(Not a Number).
While + and - may have the same Operator Precedence, they do not have the same implicit conversion rules.
As - always means number subtraction in JavaScript, using - will always implicitly attempt parsing both the left and right side of the expression as integer.
In this case, as the operator precedence is the same, and the evaluation is from left to right, you end up with (""+1+10+2) using +'s implicit tostring conversion for string concatenation, or the string "1102". Next, the - will implicitly attempt to parse the string "1102" into a number, as well as the number 5, which results in 1102-5, or the number 1097. At this point the string "8" is concatenated implicitly using +, and the end result can be seen: the string "10978".
Perhaps an interesting alternative would have been ""+1+10+2-5+8, which would have been 1097+8, or the number 1105.
Related
I was reading the re-introduction to JavaScript on MDN and in the section Numbers it said that you can convert a string to a number simply by adding a plus operator in front of it.
For example:
+"42" which would yield the number output of 42.
But further along in the section about Operators it says that by adding a string "something" to any number you can convert that number to a string. They also provide the following example which confused me:
"3" + 4 + 5 would presumably yield a string of 345 in the output, because numbers 4 and 5 would also be converted to strings.
However, wouldn't 3 + 4 + "5" yield a number of 12 instead of a string 75 as was stated in their example?
In this second example in the section about operators wouldn't the + operator which is standing in front of a string "5" convert that string into number 5 and then add everything up to equal 12?
What you are talking about is a unary plus. It is different than the plus that is used with string concatenation or addition.
If you want to use a unary plus to convert and have it added to the previous value, you need to double up on it.
> 3 + 4 + "5"
"75"
> 3 + 4 + +"5"
12
Edit:
You need to learn about order of operations:
+ and - have the same precedence and are associated to the left:
> 4 - 3 + 5
(4 - 3) + 5
1 + 5
6
+ associating to the left again:
> 3 + 4 + "5"
(3 + 4) + "5"
7 + "5"
75
unary operators normally have stronger precedence than binary operators:
> 3 + 4 + +"5"
(3 + 4) + (+"5")
7 + (+"5")
7 + 5
12
You could also use parseInt() or parseFloat(), like this:
> 1 + 2 + "3"
"33"
> 1 + 2 + parseInt(3)
6
I think that's alot cleaner than using +"3", but that is just my opinion.
The answer can be found in Ecma262.pdf section 11.6.1:
If Type(lprim) is String or Type(rprim) is String, then a. Return the
String that is the result of concatenating ToString( lprim) followed
by ToString(rprim).
So that will resolve all operations according to precedence, so that as soon the string is found any number, the number is converted to string.
4 + 3 + "5"
"75"
4 + 3 + "5" + 3
"753"
To read the whole standard, go here.
When you look at Step 7 and "Note 2" at The Addition operator ( + ) (§11.6.1) in the ES5 specs,
it says
If Type(lprim) is String` or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
NOTE 2 Step 7 differs from step 3 of the comparison algorithm for the relational operators (11.8.5), by using the logical-or operation instead of the logical-and operation.
Meaning if either 7 (3+4) or "5" (|| not &&) is typeof "string" toString() is applied to both operands.
So the addition is actually applied to
"7" and "5" -> "7" + "5" //"75"
A smple + operator in javascript is used for concatenation and not to add.
A bracket and a + operator before the string format integer variable will do the job every time.
This always works fine.
1 + (+"2") = 3
Because placing + before string converts the string variable into number.
fiddle here: http://jsfiddle.net/xuVur/2/
In the example of 3 + 4 + "5" - the Javascript parser will do (3+4)+"5", as the 3+4 is first - so it will add 3 + 4 because they are numbers, then concatenate the string "5".
When you add a number and a string in Javascript the result is always a string.
Check the experiment here - http://jsfiddle.net/xuVur/1/
var a = "3" + 4 + 5;
var b = 3 + 4 + "5";
$("#result1").html(a); // prints 345
$("#result2").html(b); //prints 75
It is confusing, but binary + seems to be a rare case of a number being coerced to a string. In most cases it would be the other way round (so it's very easy to think that you don't need to be too fussy about the type)
4+"3" = "43"
4-"3" = 1
var fir=prompt("Enter first Number");
var sec=prompt("Enter second number");
var sum=Number(fir)+Number(sec);
alert("The sum is " + sum);
alert("The difference is " + fir-sec);
alert("The product is " + fir*sec);
alert("The division is " + fir/sec);
Now: suppose fir=2 and sec=1.
The output is:
3
NaN
2
2
Why is the difference NaN instead of 1?
* and / have higher operator precedence than + and -, just like with PEMDAS order of operations in standard math. Specifically, + and - have precedence 13, whereas * and / have precedence 14.
When an expression has + and -s only, they're evaluated in left-to-right order. So, your code is equivalent to:
alert(("The Difference is " + fir) - sec);
alert("The product is " + (fir*sec));
alert("The division is " + (fir/sec));
In the second and third alert, fir and sec get combined into a single numeric expression before being concatenated with the prior string.
In the first alert, "The Difference is " + fir get put together first, resulting in another string (a string + a number results in another string). So then you have
alert((someString) - sec);
But someString - sec doesn't make sense - you can't subtract something from a string, so the expression resolves to NaN.
You can do one thing
var fir=prompt("ENter 1st Number");
var sec=prompt("Enter second number");
var sum=Number(fir)+Number(sec);
var sub=Number(fir)-Number(sec);
alert("The Sum is " + sum);
alert("The Difference is " + sub);
alert("The product is " + fir*sec);
alert("The division is " + fir/sec);
Usually, the plus operator + sums numbers.
But, if the binary + is applied to strings, it merges (concatenates) them:
let s = "my" + "string";
alert(s); // mystring
Note that if one of the operands is a string, the other one is converted to a string too.
For example:
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
See, it doesn’t matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, the other one is converted into a string as well.
However, note that operations run from left to right. If there are two numbers followed by a string, the numbers will be added before being converted to a string:
alert(2 + 2 + '1' ); // "41" and not "221"
String concatenation and conversion is a special feature of the binary plus +. Other arithmetic operators work only with numbers and always convert their operands to numbers.
For instance, subtraction and division:
alert( 2 - '1' ); // 1
alert( '6' / '2' ); // 3
reference https://javascript.info/operators
Because you're concatenating a string ("The difference is") with a number, obtaining a string, and then subtracting a number from it. Use parentheses
alert("The Difference is " + (fir-sec));
The problem you face is due to dynamic type conversion. In your second alert JS engine 1st concatenates "The Difference is " and fir and then subtracts sec. You have to add braces:
alert("The Difference is " + (fir-sec))
In all other cases it is ok because * and / operators have higher priority than + operator
Remeber Math's BODMAS theory,
in case of multiplication and division it works and giving you result.
But for substraction, it first does addition.
And finally:
String - Number = NaN
Javascript Code
I am concacting two variables and comparing with a string
Why the alert is true? Why it is not coercing??
var str1 = "2";
var str2 = "3";
var res = str1 + str2 // return 23
console.log(res) // 23
console.log("100") // 100
alert(res > "100") // alerts true instead of false
The value in res is a string. In strings "23" is greater than "100" (looking at the first character).
To further answer your question "why isn't javascript coercing" I'd like to quote a comment from James Thorpe
"Both sides are strings - there is nothing to coerce"
Here's a code example.
console.log (23 > "100") // false
console.log ("23" > "100") // true
First console.log compares number with string - javascript coerces.
Second console.log compares string with string - nothing to coerce
Alert is true because '23' is lexicographically greater than '100' ('2' > '1').
You can use parseInt to convert strings to numbers:
alert(parseInt(res) > 100);
Because you are comparing strings. "100" is lower then "23" because "1"<"2".
You should parse to int if you want numerical comparison, as shown in #jh314 answer.
You can temporarily change the string to their number representation i.e, 23 and 100 and use the comparison operator. Either prefix the values with + to change them to numeric value or use parseInt():
var str1 = "2";
var str2 = "3";
var res = str1 + str2 // return 23
console.log(res) // 23
console.log("100") // 100
alert(+res > +"100")
The value of res is "23" not 23. That means it's a string and therefore when you alert the comparison it compares the first digit of each, 2 > 1 which is true.
As for “why is it not coercing?” - because both operands are strings in both cases, and because both + and > are valid operations on strings.
(Using - (subtract) would cause implicit coercion to number because it doesn’t make sense for strings, but concatenation and addition use the same operator. Welcome to JavaScript!)
Your alert is comparing a string and a string.
Try: alert(res > 100)
What does the following evaluate to?
"1"+2+4
What about this:
5 + 4 + "3"
In the first case since "1" is a string, everything is a string, so the result is "124". In the second case, its 93.what is happening here? Why does addition happen in one instance, while string concatenation occurs in the other?
var x = "1" + 2 + 4;
var z = 5 + 4 + "3";
console.log(x); // "124"
console.log(z); // 93
Can anyone explain this?
expression evaluates from left to right.
"1"+2+3
^--^
"12" //string +3
^_____________^
"123" //string
in 2nd case
1+2+"3"
^_^
3+"3"
^___^
"33" // string
Think about the operation order (rtl or ltr) each time it performs a binary operation it converts it accordingly so 5+4 will be int and (5+4) + "3" will be a string because "3" is a string
Same method applies to different examples
var x = "1" + 2 + 4; // 124
This is taking the string "1" and concatenating to it "2" and "4" as strings.
var z = 5 + 4 + "3"; // 93
This is taking the numbers 4 and 5 and adding them together to get the number 9, and then concatenating the string "3" to that to produce another string.
The key thing to take away here is that the end result of what you're doing here is string concatenation. The order of evaluating the numbers is different but the end result is a string.
In the first case you create a string first (1) and then javascript concatenates the following number as strings (124).
In the second one you create a number first then javascript adds the second number to this first number (5 + 4 = 9) and then you add a string so it does the concatenation of 9 and 3
In both case apply the type conversion and left to right precedence.
in first one,
var x = "1" + 2 + 4; // 124
compiler take 1 as string and after that it will concatenating with 2 now 12 is the string so it will concatenate with 4 and result will produce "124" as string.
var z = 5 + 4 + "3"; // 93
in Second one,
first 5 and 4 is numeric so make addition and result will be 9. and this will concatenate with string 3 soo output will be 93 as string.
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);