This question already has answers here:
How to evaluate a math expression given in string form?
(26 answers)
Closed 1 year ago.
I am working on a discord.js and have a found the following problem, I want to convert the users input into a number I am working on a calc bot so the arguments were like 10/2 but I couldn't find a method of converting the string into a number so I thought i would ask, I thought maybe the Number function could work but it didn't and tried using arrays but the join function simply converts it to a string. Anyone know how to solve this?
If you want to avoid the use of eval, you need to parse out the numbers, convert them to numbers, and perform the appropriate operation.
const rx = /(\d+(?:\.\d+)?)\s*([+\-\*\/%])\s*(\d+(?:\.\d+)?)/;
function math(str) {
const [full, lhs, op, rhs] = rx.exec(str);
let retval
switch (op) {
case '+':
retval = Number(lhs) + Number(rhs);
break;
// etc...
}
return retval;
}
console.log("1 + 1 = ", math("1 + 1"));
console.log("1.1 + 1.1 = ", math("1.1+1.1"));
Note that the code above doesn't have any error checking to bail if the string provided isn't a valid operation, or if the numbers aren't really numbers. It's only an example of how you can use a regular expression to get these values, and avoid using the potentially dangerous eval.
The easiest way to do this is by using eval() which takes a string containing javascript code, evaluates it, and returns the result.
WARNING: this is very dangerous and you can send any javascript code with it and javascript will happily execute it.
This would give users of the bot the ability to do any command and basically take remote control of your computer/server.
To protect yourself from this you should make sure that the string only contains some allowed characters like this:
const allowedChars = "1234567890/*+-% ";
const input = "2323 + 323";
if (![...input].some(x => !allowedChars.includes(x))) {
// safe to evaluate
const result = eval(input);
} else {
// not safe to execute
}
Related
This question already has answers here:
Issue with combining large array of numbers into one single number
(3 answers)
Closed 1 year ago.
I have the following array and I want to join it into a number
const arr = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
const digits = arr.join("") //6145390195186705543
const digitsToNumber = +arr.join("") //6145390195186705000
console.log(digits);
console.log(digitsToNumber);
You can see that the join function works. However, when I try to convert it into a number, it shows a weird value. Do you guys know why it happened that way?
As stated in the comments, the value is too large for JavaScript and is truncated.
We can use BigInt to prevent this. Use with caution!
const arr = [6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]
const digits = arr.join('');
const digitsToNumber = +arr.join("");
const bigDigitsToNumber = BigInt(arr.join(''));
console.log(digits); // 6145390195186705543
console.log(digitsToNumber); // 6145390195186705000
console.log(bigDigitsToNumber.toString()); // 6145390195186705543
They will log different results because you are exceeding Number.MAX_SAFE_INTEGER - the highest value JS can safely compare and represent numbers.
One method to check if you are ever exceeding the limit (besides remembering the value) is Number.isSafeInteger()
Number.isSafeInteger(digitsToNumber); //false
From the docs: For larger integers, consider using the BigInt type.
To convert your concatenated string into a number you could use parseInt("123") method.
const number= parseInt(digitsToNumber)
However because of your number is too big or could be bigger, Javascript can not handle that numbers which contains more than 16 digit. If you also have a problem like that you can use some external big number libraries like BigNumber.Js.
Edit: According to Teemu's comment, you could also use link native big integer handling library.
This question already has answers here:
Sum all the digits of a number Javascript
(8 answers)
Closed 3 years ago.
I am trying to solve this function challenge and get the requested output. I tried to come up with a solution but this is beyond my me. Please help me understand this so I can solve this challenge,
I researched using an array but I don't know how to separate the elements(integers) so I can add them.
function getSumOfDigits(num) {
return num + num;
}
/* Do not modify code below this line */
console.log(getSumOfDigits(42), '<-- should be 6');
console.log(getSumOfDigits(103), '<-- should be 4');
I am not getting an error message but the input is returning the wrong output.
EDIT: To add explanation for the answer and include a solution provided on the comment line.
You can convert the number into string so you can be able to manipulate each digit inside the number. To perform arithmetic operation on the digits, you will need to convert the characters back to numbers.
function getSumOfDigits(num) {
let str = num.toString();
let sum = 0;
for(value of str)
sum += Number(value);
return sum;
}
For future reference I have included the elegant solution provided on the comment line below (credit to #Scott Sauyet):
getSumOfDigits = (nbr) => String(nbr).split('').map(Number).reduce((a, b) => a + b, 0);
In both cases you can call the function like:
console.log(getSumOfDigits(42));
console.log(getSumOfDigits(103));
The link provided on the question above has a lot more solutions to this problem.
This question already has answers here:
Validate decimal numbers in JavaScript - IsNumeric()
(52 answers)
Closed 5 years ago.
I’m loading a JSON file a reading the values into an array using a for loop
I’m concerned that sometimes the JSON file might become corrupted ie the values Im reading in might become ASCII letters ie 1t3 where the value should of been 123
Is there a test case where you could say if values[a] does not equal a number then set it to “ “ or blank
Thanks,
Ben
You could use the parseInt() function and check if it returns an integer or NaN. You can check out information on it on W3schools or the MDN Web Docs.
However, in my opinion, it would be better to use regular expressions. If you read the w3schools examples for parseInt(), they show that "0x10" is read as 16.
For a regular expression, try the following:
function isNumber(n) {
// Added checking for period (in the case of floats)
var validFloat = function () {
if (n.match(/[\.][0-9]/) === null || n.match(/[^0-9]/).length !== 1) {
return false;
} return true;
};
return n.match(/[^0-9]/) === null ? true : validFloat();
}
// Example Tests for Code Snippet
console.log(isNumber("993"));
console.log(isNumber("0t1"));
console.log(isNumber("02-0"));
console.log(isNumber("0291"));
console.log(isNumber("0x16"));
console.log(isNumber("8.97"));
The MDN Web Docs have a super helpful page on Regular Expressions.
I have a string expression like such: "1+2+3", and it must stay as a string. In other words, looping and casting the digits to perform the operation isn't an option, so my solution is eval("1+2+3"). But eval() is slow and has all these issues associated with it. Is there an alternative to evaluate my string?
Evaluating a string is not only slow, it's dangerous. What if, by malicious user intent or error, you end up evaluating code that crashes your program, destroys your data o opens a security hole?
No, you should not eval() the string. You should split it, cast the operands to numbers, and sum them.
You can keep the string around if you like (you said you needed the string), but using the string to actually perform this operation is a Really Bad Idea.
var string = "1+2+3"
var numbers = string.split('+').map(function(x) { return parseInt(x) })
var sum = numbers.reduce(function(total, x) { return total + x }, 0)
This is a silly question:
var reducer = function (a, b) {
return +a + +b;
};
"1+2+3".match(/[+-]?\d+/g).reduce(reducer); // 6
// or addition only
"1+2+3".split(/\D/).reduce(reducer); // 6
I've always converted numbers to strings by adding an empty string to them:
var string = 1 + '';
However, JSLint complains of this method with Expected 'String' and instead saw ''''., and it does look a little ugly.
Is there a better way?
I believe that the JSLint approved way is to call .toString() on the number:
var stringified = 1..toString();
// Note the use of the double .. to ensure the the interpreter knows
// that we are calling the toString method on a number --
// not courting a syntax error.
// You could also theoretically call 1["toString"];
(Sorry, it possibly would've been better to say this as a comment above but I haven't yet earned the right to post comments, so...)
Remember that jslint is not just validating whether your JavaScript will actually run, it is trying to enforce coding style with the aim of helping you produce more readable and maintainable code.
So 1 + '' works, but isn't necessarily the most readable option for everybody while explicit casting options (see the other answers) should be readable for everybody. Of course if nobody else will ever see your code you need only worry about whether you will be able to understand it if you come back to it next month, or next year...
Don't forget that the following two statements don't produce the same result:
var s1 = 1 + 3 + ''; // gives '4'
var s2 = '' + 1 + 3; // gives '13'
I assume 1 + '' is just a simplification for discussion though, or why not just use '1' in the first place?
You can use the .toString() method like so:
var num = 1;
var str = num.toString();
There's also (at least in Chrome): String(1) without new.
var n = 1, s = String(n);
I am going to say "bug" or "mis-feature"
Cole Consider that
var x = "foobar" + 1;
is "approved" jslint. In any case, it is 100% valid Javascript.
Happy coding.
For comment:
This is why I prefer to use the string literal as the first operand as this shows intent -- knowing a language is fundamental to using a language.
The only place the duck-typing is an issues (in this case) is with an expression of the form a + b, where neither is a string literal. In this case a (or b) may evaluate to a string where it was expected to evaluate to a number (this would trigger the string concatenation vs. the expected numeric addition). If any of the operands are a string literal the intent is well-defined/described.
This particular "issue", however, is not present in the posted code; nor would it be eliminated with the use of toString over a string literal.
In my opinion, we should use String(number) instead of number + '' or number.toString(), because
number + '' will trigger the JSLint error
number.toString() will fail in case number is null or undefined, and you will have TypeError: number is undefined / null
Recently, JSLint was in beta. The new version no longer complains about this code:
function convert(x) {
'use strict';
// alert(typeof x);
x = x + "";
// alert(typeof x);
return x;
}
convert(3);