Preventing concatenation - javascript

I've been writing JavaScript on and off for 13 years, but I sort of rediscovered it in the past few months as a way of writing programs that can be used by anyone visiting a web page without installing anything. See for example.
The showstopper I've recently discovered is that because JavaScript is loosely typed by design, it keeps concatenating strings when I want it to add numbers. And it's unpredictable. One routine worked fine for several days then when I fed different data into it the problem hit and I ended up with an impossibly big number.
Sometimes I've had luck preventing this by putting ( ) around one term, sometimes I've had to resort to parseInt() or parseFloat() on one term. It reminds me a little of trying to force a float result in C by putting a .00 on one (constant) term. I just had it happen when trying to += something from an array that I was already loading by doing parseFloat() on everything.
Does this only happen in addition? If I use parseInt() or parseFloat() on at least one of the terms each time I add, will that prevent it? I'm using Firefox 6 under Linux to write with, but portability across browsers is also a concern.

The specification says about the addition operator:
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)
Which means that if at least one operator is a string, string concatenation will take place.
If I use parseInt() or parseFloat() on at least one of the terms each time I add, will that prevent it?
No, all operands have to be numbers.
You can easily convert any numerical string into a number using the unary plus operator (it won't change the value if you are already dealing with a number):
var c = +a + +b;

I normally do this:
var x = 2;
var t = "12";
var q = t+x; // q == "122"
var w = t*1+x; // *1 forces conversion to number w == 14
If t isn't a number then you'll get NaN.
If you multiply by 1 variables you don't know what type they are. They will be converted to a number. I find this method better than doing int and float casts, because *1 works with every kind of numbers.
The problem you are having is that the functions which fetch values from the DOM normally return strings. And even if it is a number it will be represented as a string when you fetch it.

You can use + operator to convert a string to number.
var x = '111'
+x === 111

Rest assured it is very predictable, you just need to be familiar with the operators and the data types of your input.
In short, evaluation is left-to-right, and concatenation will occur whenever in the presence of a string, no matter what side of the operation.
So for example:
9 + 9 // 18
9 + '9' // '99'
'9' + 9 // '99'
+ '9' + 9 // 18 - unary plus
- '9' + 9 // 0 - unary minus
Some ternary expressions:
9 + '9' + 9 // '999'
9 + 9 + '9' // '189'

Related

Why am I getting a number and not a concatenated string?

I have this code
var n = parseInt(prompt("Give me a number"));
var sum = 0;
for (let i=0; i < n.toString().length; i++){
let expon = n.toString()[i] ** n.toString().length;
sum += expon;
}
My doubt is the following: If my n is 371, n.toString()[0] is '3' (A STRING!!), why is it then that when I do ** n.toString().length (which is 3). I get 27 ?!!?
Also, it is clear to me that if x = '3' and I do x + x I get '33' and not 6. Can this happen to the addition only? why?
'3' ** 3 is 27 because ** converts both its arguments to numbers if possible. It has no function other than numeric exponentiation.
'3' + 3 is '33' because + has multiple possible functions (addition and string concatenation), and if at least one of the arguments is a string, string concatenation is used instead of addition. In another universe, it may well attempt to do numeric addition first and end up at 6, but the language designers of our universe chose to do it this way round.
Check this: https://medium.com/swlh/strings-and-basic-mathematical-operators-in-javascript-e9de3d483dae
In simple words - in JavaScript, when trying to add String type to non-String type, adding operator automatically casts added elementsto both be set of characters, because '+' can be understood as adding OR as concatenating. Although, every different arithmetic operations (substracting, dividing, multiplying, powering, etc.) performed on String and non-String type will force the first one to be casted to the Number form. If not possible, we will receive NaN result.

Javascript 19 digits number changing the last digits to zeroes

I ran into this issue when trying to get the last 4 digits of a 19 digits numeric value.
let payload={
card: 1234567891238475891
}
let stringCardNumber = '' + payload.card;
console.log(payload.card)
console.log(stringCardNumber)
console.log( stringCardNumber.slice(stringCardNumber.length - 4))
let zeroedCardNumber = stringCardNumber.slice(0, 6) + "".padStart(stringCardNumber.length - 10, "0") + stringCardNumber.slice(stringCardNumber.length - 4);
console.log(zeroedCardNumber)
So for 1234567891238475891, the output log is 1234567891238475800.
Changing the card value to string in the json itself is not the solution I am expecting, since there will be cases where 19 digits number is expected.
That number is too large for JavaScript's default numerical representation so you need to use the longer form with BigInt:
card: 1234567891238475891n
A better approach is to just use a string as these aren't really "numbers" in the conventional sense and as Pointy adds, support for BigInt is a relatively new thing so if support for older browsers is important it won't be a solution.
JSON does not enforce BigInt support, so numerical values this large may well get rounded. Using a string is the most reliable way to ensure this data flows through correctly.

Javascript: "+" sign concatenates instead of giving sum of variables

I am currently creating a site that will help me quickly answer physics questions.
As it happens, the code didn't run as expected, here is the code
if (option == "dv") {
var Vinitial = prompt("What is the Velocity Initial?")
var acceleration = prompt("what is the acceleration?")
var time = prompt("what is the time?")
Vfinal = Vinitial + acceleration * time
displayV.innerHTML = "v= vf= " + Vfinal + "ms" + sup1.sup();
}
Now, let's say Vinitial was 9, acceleration was 2, and time was 3.
When the code runs, instead of getting 15 for "Vfinal", I get 96.
I figured out that it multiplies acceleration and time fine, and then just concatenates the 9 at the beginning, with 6 (the product of 2 * 3).
I have fixed it for now by using
Vfinal = acceleration * time - (-Vinitial)
which avoids using the "+" sign, but I don't want to have to keep doing this. How do I fix it?
you are dealing with strings here, and math operations on strings will mess up. Remember when ever you are doing math operations you have to convert the data into actual numbers and then perform the math.
Use parseInt() more Details here
Your code should change to
Vfinal = parseInt(Vinitial,10) + parseInt(acceleration,10) * parseInt(time,10);
Edit 1: If the numbers are decimal values then use parseFloat() instead
So the code would be
Vfinal = parseFloat(Vinitial) + parseFloat(acceleration) * parseFloat(time);
Object-Oriented JavaScript - Second Edition: As you already know, when you use the plus sign with two numbers, this
is the arithmetic addition operation. However, if you use the plus
sign with strings, this is a string concatenation operation, and it
returns the two strings glued together:
var s1 = "web";
var s2 = "site";
s1 + s2; // website
The dual purpose of the + operator is a source of errors. Therefore,
if you intend to concatenate strings, it's always best to make sure
that all of the operands are strings. The same applies for addition;
if you intend to add numbers, make sure the operands are numbers.
You can use "+" operator with prompt() to convert returned values from string to int
var Vinitial = +prompt("What is the Velocity Initial?");
var acceleration = +prompt("what is the acceleration?");
var time = +prompt("what is the time?");
Explanation:
var a = prompt('Enter a digit');
typeof a; // "string"
typeof +a; // "number"
If you will enter non-digit data +a gives you NaN. typeof NaN is "number" too :)
You will get the same result with parseInt():
var Vinitial = parseInt(prompt("What is the Velocity Initial?"), 10);
var acceleration = parseInt(prompt("what is the acceleration?"), 10);
var time = parseInt(prompt("what is the time?"), 10);
developer.mozilla.org: parseInt(string, radix);
string: The value to parse.
radix: An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the above mentioned string.
Specify 10 for the decimal numeral system commonly used by humans.
Always specify this parameter to eliminate reader confusion and to
guarantee predictable behavior. Different implementations produce
different results when a radix is not specified, usually defaulting
the value to 10.
Epilogue:
Object-Oriented JavaScript - Second Edition: The safest thing to do is to always specify the radix. If you omit the radix, your code
will probably still work in 99 percent of cases (because most often
you parse decimals), but every once in a while it might cause you a
bit of hair loss while debugging some edge cases. For example, imagine
you have a form field that accepts calendar days or months and the
user types 06 or 08.
Epilogue II:
ECMAScript 5 removes the octal literal values and avoids the confusion
with parseInt() and unspecified radix.
The Problem is, Your value has been took it in a form of string .. so convert your value into Int using parseInt(accelaration).. then it will work ..
Vfinal = parseInt(Vinitial) + parseInt(acceleration) * parseInt(time)
//use ParseInt
var a=10,b=10;
var sum=parseInt(a+b);
ex:
parseInt(Vinitial + acceleration) * time

Can someone please explain this JavaScript decimal rounding function in detail?

function Round2DecimalPlaces(l_amt) {
var l_dblRounded = +(Math.round(l_amt + "e+2") + "e-2");
return l_dblRounded;
}
Fiddle: http://jsfiddle.net/1jf3ut3v/
I'm mainly confused on how Math.round works with "e+2" and how addition the "+" sign to the beginning of Math.round makes any difference at all.
I understand the basic of the function; the decimal gets moved n places to the right (as specified by e+2), rounded with this new integer, and then moved back. However, I'm not sure what 'e' is doing in this situation.
eX is a valid part of a Number literal and means *10^X, just like in scientific notation:
> 1e1 // 1 * Math.pow(10, 1)
10
> 1e2 // 1 * Math.pow(10, 2)
100
And because of that, converting a string containing such a character sequence results in a valid number:
> var x = 2;
> Number(x + "e1")
20
> Number(x + "e2")
200
For more information, have a look at the MDN JavaScript Guide.
But of course the way this notation is used in your example is horrible. Converting values back and forth to numbers and strings is already bad enough, but it also makes it more difficult to understand.
Simple multiple or divide by a multiple of 10.
The single plus operator coerces a the string into a float. (See also: Single plus operator in javascript )

why is 10 * (7/10) = 7 in JavaScript?

7 and 10 in the expression (7/10) are integers, so the result 0.7 should be integer as well, which is 0, and the result for the entire expression should be 0 too. However, it's giving me the result of 7, why? Is it ignoring the parentheses or converts to double automatically?
JavaScript doesn't distinguish between integers and floating point numbers, everything I believe is considered a double so that is just why you get the result.
Take a look at the details on the Number property on MDN.
JavaScript doesn't have an integer type, or a double, or a float... it just has 1 type for all numbers: the helpfuly called Number type (try var foo = new Number(7);, or var foo = Number('123string');
Now, I know I said that JS doesn't know of floats, but that's not entirely true. All Number type vars/values are, essentially 64 bit floats, as defined by the IEEE 754 standard (which are, indeed, as Jan Dvorak kindly pointed out to me, double's in most staticly typed languages), with all the caveats that brings with it:
(.1 + .2);//0.30000000000000004
But that's not the point. The point is that, in JS you can perform float + int arithmatic without there ever being a need for internal casts, or conversions. That's why 10*(7/10) will always be 7
There is no int and double in JavaScript
In JavaScript, both int, flot, and double are normalized to work together. They are treated as 1 (They're treated as as Number, which is an IEEE 754 float. Thanks #Elias Van Ootegem). Equality, Liberty and Fraternity. and thus;
10*0.7 = 7
JavaScript is not like C.
Javascript doesn't have integers, and even if it did, there's nothing that says that / needs to return an integer (just because another language may do that doesn't mean every language has to). The operation results in a float/Number, just like all Javascript numbers are, period.
try this
10*parseInt(7/10)
hope this will help you
If you try to follow the rules, then
10 * (7/10) --> 10 * .7 --> 7
You cannot change the way its gonna result into.
so the result 0.7 should be integer as well, which is 0
If you want this, then try using
Math.Floor();
This would change the decimals to the nearest int! Or try out parse()
JavaScript uses dynamic types. That means that a variable like this:
var str = "hi";
Can later become:
str = 123; //now we have an 'int'
str += 0.35; //now str is 123.35, a 'float'
So JavaScript doesn't cast floats to ints for example.
If you want to force a "cast" then you have to do:
var integer = parseInt( 3.14*9.0291+23, 10 ); //the second parameter (10) is the 'base'
But remember, Javascript will not take care of types, that's your problem.

Categories

Resources