Is it possible to make an operator type of string into operator
<script>
var operator = $(this).val(); returns a string eg) + or -
var quantity = 5 operator 1;
</script>
currently i am using switch
It's possible, in a way, via eval, but see caveats. Example:
var result = eval("5 " + operator + " 1"); // 6 if operator is +
The problem with eval is that it's a full JavaScript evaluator, and so you have to be really sure that the content is under your control. User-contributed content, for instance, is something you have to be very, very cautious with.
Alternately, just do a switch:
switch (operator) {
case "+":
result = 5 + 1;
break;
case "-":
result = 5 - 1;
break;
case "/":
result = 5 / 1;
break;
case "*":
result = 5 * 1;
break;
// ...and so on, for your supported operators
}
The absolutely most simple way would be to use a if:
var operator = $(this).val(); // returns a string eg) + or -
var quantity;
if(operator === '-') {
quantity = 5 - 1;
} else if(operator === '+') {
quantity = 5 + 1;
}
You could also use the eval function, but eval is very rarely recommended and is not really worth it in a case like this.
No. The easiest would be to use eval:
var quantity = eval("5 " + operator + " 1");
but it is considered a bad practice. Eval is Evil. Not only do you have security concerns, it also slows down the execution of your code.
Rather, this approach is much better and safer:
var operators = {
"+": function(a, b) { return a + b; };
"-": function(a, b) { return a - b; };
};
var operatorFunction = operators[operator];
if (operatorFunction) {
var quantity = operatorFunction(5, 1);
}
Related
I have a code but it is not working for operator precedence. It is normally executing from first to last operator entered in a string.
It gives correct answer while string follow precedence rule(eg."12 * 10 / 5 + 10 - 1" = 33 <- correct answer). But it gives wrong answer while string doesn't follow precedence rule(eg. "15 + 10 * 5 / 10 - 1" = 49 <- wrong answer. actual answer is 19)
code:
var str="12 * 10 / 5 + 10 - 1";
var res=[],n1=[],num=[],op=[],o1=[];
var result;
res= str.split(" ");
console.error("res",res);
document.write(res.join(",")+"<br>");
for(var i=0;i<res.length;i++)
{
if(i%2==0)
{
num.push(parseInt(res[i]));
}
else
{
op.push(res[i]);
}
}
document.write(num+"<br>");
document.write(op+"<br>");
var myFunction = function(num1,num2,oper){
var j;
if(oper=='-'){
j = num1-num2;
return j;
}else if(oper=='+'){
j = num1+num2;
return j;
}else if(oper=='*'){
j = num1*num2;
return j;
}else if(oper=='/'){
j = num1/num2;
return j;
}else{
j = 0;
return j;
}
}
var x=num[0];
for(var i=1; i<num.length; i++){
x = myFunction(x,num[i],op[i-1]);
}
document.write("result of "+str+" is "+x+"<br>");
Here's one way to do it. I like because this is how we craft a parser. There are other approaches as mentioned, usual when you're using a parser generator like lex/yacc.
As you have noticed, there are times we need to save an intermediate result in order to process another part of an expression. This way, called a recursive descent parser, uses the environment's own stack to save the temp results. Another way is to use maintain a stack yourself, but that's not much valuable.
This is also very flexible. It's pretty easy to extend the grammar to different precedence levels. Change parseFactor below to parse negation and parentheses.
function parse(expression) {
return expression.split(' ')
}
function consumeNumber(tokens) {
const token = tokens.shift()
return parseInt(token)
}
function consumeOp(tokens, allowed) {
const token = tokens[0]
if (allowed.indexOf(token) >= 0) {
tokens.shift()
return token
}
}
function parseFactor(tokens) {
return consumeNumber(tokens)
}
function parseTerm(tokens) {
let value = parseFactor(tokens)
let op
while (op = consumeOp(tokens, ['*', '/'])) {
let nextVal = parseFactor(tokens)
switch (op) {
case '*':
value *= nextVal
break
case '/':
value /= nextVal
break
}
}
return value
}
function parseExpression(tokens) {
let value = parseTerm(tokens)
let op
while (op = consumeOp(tokens, ['+', '-'])) {
let nextVal = parseTerm(tokens)
switch (op) {
case '+':
value += nextVal
break
case '-':
value -= nextVal
break
}
}
return value
}
function evaluate(expression) {
const tokens = parse(expression)
return parseExpression(tokens)
}
evaluate('15 + 10 * 5 / 10 - 1')
Here's a hacked together (read: shouldn't actually be used anywhere real without extra work / error checking) object which gets the correct answer for both test cases. I'm sure this could be improved on and there's likely better algorithms for this. As per my comment it just scans for * or / and processes that calculation, then generates a new number/operator set including that result. I mainly just wrote it for fun.
I haven't bothered with the code to try and parse the string, this just takes an array of numbers and an array of operators.
(Also I get 11.5 as the incorrect result for your second test, both manually and running your code)
<script>
myCalc = {
getResult: function(n, o){
this.numbers = n;
this.operators = o;
// keep going until our list of numbers is just the final result
while( this.numbers.length > 1 )
this.findNext();
return this.numbers[0];
},
findNext: function(){
var opIndex = 0;
// find the next * or / operator
for(i=0;i<=this.operators.length;i++){
if( this.operators[i] == '*' || this.operators[i] == '/' ){
opIndex = i;
break;
}
}
var opResult = this.doCalc(this.operators[opIndex], this.numbers[opIndex], this.numbers[opIndex+1]);
// update our main numbers list and splice out the operator we just processed
// replace "x" with the result, and splice "y"
this.numbers[opIndex] = opResult;
this.numbers.splice(opIndex + 1, 1);
this.operators.splice(opIndex, 1);
console.log(this.numbers);
console.log(this.operators);
},
doCalc: function(op,x,y){
switch(op){
case '*':
return x * y;
case '/':
return x / y;
case '+':
return x + y;
case '-':
return x - y;
}
return 0;
}
};
console.log(myCalc.getResult([15,10,5,10,1], ['+','*','/','-']));
console.log(myCalc.getResult([12,10,5,10,1], ['*','/','+','-']));
</script>
Since nobody mentioned it before, you could simply process your string with eval function:
var str="15 + 10 * 5 / 10 - 1";
console.log(eval(str));
// logs 19
If the argument is an expression, eval() evaluates the expression
im just started to learn JavaScript and i´m trying to simplify some code, but couldn´t get a working solution. The working part is this:
switch (v) {
case 0:
if (localStorage.FGAz0) {
localStorage.FGAz0 = Number(localStorage.FGAz0)+1;
} else {
localStorage.FGAz0 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz0+ " Visitor(s).";
break;
case 1:
if (localStorage.FGAz1) {
localStorage.FGAz1 = Number(localStorage.FGAz1)+1;
} else {
localStorage.FGAz1 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz1+ " Visitor(s).";
break;
case 2:
if (localStorage.FGAz2) {
localStorage.FGAz2 = Number(localStorage.FGAz2)+1;
} else {
localStorage.FGAz2 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz2+ " Visitor(s).";
break;
case 3:
if (localStorage.FGAz3) {
localStorage.FGAz3 = Number(localStorage.FGAz3)+1;
} else {
localStorage.FGAz3 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz3+ " Visitor(s).";
break;
case 4:
if (localStorage.FGAz4) {
localStorage.FGAz4 = Number(localStorage.FGAz4)+1;
} else {
localStorage.FGAz4 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz4+ " Visitor(s).";
break;
case 5:
if (localStorage.FGAz5) {
localStorage.FGAz5 = Number(localStorage.FGAz5)+1;
} else {
localStorage.FGAz5 = 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FGAz5+ " Visitor(s).";
break;
default:
if (localStorage.FahrGastAnzahl) {
localStorage.FahrGastAnzahl = Number(localStorage.FahrGastAnzahl)+1;
} else {
localStorage.FahrGastAnzahl= 1;
}
document.getElementById("Ergebnis").innerHTML = "You have " + localStorage.FahrGastAnzahl+ " Visitor(s).";}
} else {
document.getElementById("Ergebnis").innerHTML = "Sorry, dein Browser unterstützt die Speicherung von lokalen Daten nicht...";
}
and i am trying to short it to the var depending on "v" which only had numbers. At the moment i have this:
if (localStorage.FGAz + "v") {
(localStorage.FGAz + "v") = Number(localStorage.FGAz + "v")+1;
} else {
(localStorage.FGAz + "v") = 1;
document.getElementById("Ergebnis").innerHTML = "You have " + (localStorage.FGAz + "v") + " Visitor(s).";}
Something isn´t right with the adding of the variable "v", but i don´t know what and didn´t found a solution on searching. Hope someone can help me. Please no jquery, i haven´t learned that yet.
Firs of all, make sure you understand the difference between v and "v":
v is a variable name, which can hold any value (string, number, etc), eg:v = 1; v = "1"; v = "xxx";
"v" (mind the brackets) is a string value itself (v = "v", where v is the variable name and "v" is the variable value). Everything inside the brackets (" or ') is a string.
If you wish to cast numerical (integer in this example) value to string, you can use v.toString() or simply append an empty string to the value v + "".
Secondly, please get some knowledge on Property Accessors.
In short: you can access properties of an object in two different ways: using dot notation (localStorage.FGAz1) or brackets notation (localStorage["FGAz1"]).
Appending string value to dot notated property accessor (document.getElementBy + "Id") will firstly evaluate the value of property (document.getElementBy - which evaluates to undefined) and THEN will concatenate it with the string (undefined + "Id" - which results in "undefinedId"). On the other hand, appending string to accessor value inside bracket notation (document["getElementBy" + "Id"]) will firstly evaluate the value of accessor ("getElementBy" + "Id" - which evaluates to "getElementById"), and then access the object's property (document["getElementById"] - which returns the function).
Based on your example:
localStorage.FGAz is not defined, so the localStorage.FGAz + "v" evaluates to undefined + "v" which results in "undefinedv" (Notice the 'v' added to the end of 'undefined'). Sentence if ("undefinedv") always evaluates to true (HERE you can find out why).
In conclusion:
Use brackets notation:
if (localStorage['FGAz' + v.toString()]) {. This will evaluate to if (localStorage['FGAz1']) { for v = 1, if (localStorage['FGAzXXX']) { for v = XXX and so on.
I'm hoping it makes sens to you, if not leave me a question in comments.
I'm looking at the code above and it looks like you're doing some sort of visitor counter. However the localstorage would only work for the one person.
If you're going to be doing vistor counter, you could use ajax to send the information to a database and then check how many people are online.
Simple visit counter:
JSFIDDLE LINK
Code from JSFIDDLE
<div id="visitCount"></div>
if (localStorage.visitCount){
localStorage.visitCount = Number(localStorage.visitCount)+1;
} else {
localStorage.visitCount = 1;
}
document.getElementById("visitCount").innerHTML = "You've been to this page "+ localStorage.visitCount + " time(s)."
Instead of using
localStorage.FGAz + "v"
Use
localStorage["FGAz" + v]
v in "" quotations makes it a string value not variable.
My problem is simple but I can't find a way to make thag work
The idea is that if a variable (number) mets a condittion defined on another variable (cond), run some code
Example:
var cond = '> 4';
var number = 5;
// Some type of if statement to check if 5 is > 4
You can use eval but usually if you resort to eval, you're not understanding the problem correctly.
var cond = '> 4';
var number = 5;
if (eval(number + cond)) {
console.log(number + cond);
}
Another possibility would be to create functions which correlate with the condition then store the operand in another variable.
var compareFunctions = {
'>': function(a, b) {
return a > b;
}
};
var op = '>';
var operand = 4;
var number = 5;
if (compareFunctions[op](number, operand)) {
console.log(number + op + operand);
}
Do you mean like this?
if (eval(number+cond)){
console.log("success");
}
You could use a function for the check of the condition.
var cond = function (x) { return x > 4; };
var number = 5;
console.log(cond(number));
The simple, but likely dangerous and ugly way would be to use eval()
var cond = '> 5';
console.log(eval(4 + cond));
console.log(eval(6 + cond));
However, this is dangerous because if that string is in any way coming from the user, they could enter bad things and make bad things happen.
A more proper way to handle it would be to parse it properly:
let cond = '> 5';
const evaluateCondition = (value, condition) => {
// Allows for >, <, >=, <=, !=, ==
let [, operator, operand] = condition.match(/^\s*(>|<|>=|<=|!=|==)\s*(\d+)$/);
switch(operator) {
case '>':
return value > operand;
case '<':
return value < operand;
case '==':
return value == operand;
// ... implement other operators here
}
};
console.log(evaluateCondition(4, cond));
console.log(evaluateCondition(6, cond));
This will let you define valid operators and handle them in a safe manner, also easily catching invalid input.
Below was done before an edit changed the question.
You have to declare the variable outside of it, but you can set it pretty easily. The syntax I would use looks like this:
var a = 5, b;
a == 5 && (b = 2);
The bit after the && only executes if the first condition is true. To set a variable in a syntax like this, you just wrap it in parentheses.
The more traditional way would be to use an if statement:
var a = 5, b;
if (a == 5) {
b = 2;
}
If you declare the second variable inside of the if statement, it doesn't exist outside of it:
var a = 5;
if (a == 5) {
var b = 2;
}
console.log(b) // undefined
which might be what was tripping you up.
You could use eval just be careful and make sure you read up on eval first:
var cond = '> 4';
var number = 5;
console.log(eval(("" + number + cond)));
Any basic addition, subtraction, multiplication and division equation can be entered in the console or set to a variable:
var solve = (3 + 7) + 2 * 8 / 2 // 18
and correctly solved.
My code is not doing this. I believe it has something to do with the textarea. When I enter (3 + 7) + 2 * 8 / 2 it displays (3 + 7) + 2 * 8 / 2 (instead of 18). Note that my code doesn't have a solve button, it solves as the problem is entered.
Fiddle: http://jsfiddle.net/kt4SL/
HTML
<textarea cols="50" rows="10" id="pSolve"></textarea>
<div id="answer"></div>
JavaScript
var input = document.getElementById("pSolve");
input.onkeyup = function() {
// Solve the input
finalAnswer = pSolve.value;
// Display answer
answer.innerHTML = finalAnswer;
}
I tried this:
// Solve the input
finalAnswer = Number(pSolve.value);
thinking it would fix it but it didn't work. Instead nothing was displayed. What am I missing or doing wrong?
Just use eval to evaluate the equation.
answer.innerHTML = eval(finalAnswer);
I updated your jsFiddle
Have a look at this answer as well. The question was about parsing a formula but it's pretty much usable for anything really.
You are just extracting a String from the text area and pasting it into the answer div. Strings are not just evaluated by javascript! What you are actually doing is var solve = '(3 + 7) + 2 * 8 / 2';! You would need a parser to actually solve that problem, like in this SO post.
You need to do more than that to solve the equations entered in a text box. Your current script only displays the content of the text box as is. You should use MathJS. It should help.
MathJS Home
You can do repeated replacement to evaluate arithmetic expressions thus:
function performOp(_, a, op, b) {
switch (op) {
case '+': return +a + +b;
case '-': return +a - +b;
case '*': return +a * +b;
case '/': return +a / +b;
}
}
function evaluateArithmetic(expr) {
expr = expr.replace(/\s+/g, '');
while (true) {
var oldExprPS = expr;
while (true) {
var oldExprDM = expr;
expr = expr.replace(/\((-?\d+)\)/g, '$1');
expr = expr.replace(/(-?\d+)([*\/])(-?\d+)/g, performOp);
expr = expr.replace(/\((-?\d+)([+\-])(-?\d+)\)/g, performOp);
if (expr == oldExprDM) { break; }
}
expr = expr.replace(/(-?\d+)([+\-])(-?\d+)/g, performOp);
if (expr == oldExprPS) { break; }
}
return +expr;
}
var input = document.getElementById("pSolve");
input.onkeyup = function() {
// Solve the input
finalAnswer = evaluateArithmetic(pSolve.value);
// Display answer
answer.innerHTML = finalAnswer;
};
I am creating a program in javascript and I don't know how I can achieve following; My program takes argument such as "+","-" and other mathematical operators as string which I want to convert to real operators. For example (Pseudo-code):
function calc(a,b,c, op1,op2){
output=(a op1 b op2 c)
}
calc(2,3,4,"+","-")
Output should be now = 2+3-4.
However, I don't know in advance how many operators I will have and also the numbers. In other words, my objective is to replace 1,"+",2, "-",4,"+","(",5,"+",6,")".........and so on with 1+2-4+(5+6).....
How can I implement this in a nice manner?
Well, you could use eval but you can do simply this :
var funcs = {
'+': function(a,b){ return a+b },
'-': function(a,b){ return a-b }
};
function calc(a,b,c, op1,op2){
return funcs[op2](funcs[op1](a, b), c);
}
You can easily extend the funcs map with other operators.
I really would suggest using eval for this particular case:
eval("var res = " + 1 + "+" + 2 + "-" + 4 + "+" + "(" + 5 + "+" + 6 + ")");
console.log(res); //10
I know, I know, everone says you should avoid eval where possible. And they are right. eval has great power and you should only use it with great responsibility, in particular when you evaluate something, that was entered by the end user. But if you are careful, you can use eval and be fine.
This has been done very quickly, but should do the trick(JSFiddle here):
function executeMath() {
if (arguments.length % 2 === 0) return null;
var initialLength = arguments.length,
numberIndex = (initialLength + 1)/2,
numbers = Array.prototype.splice.call(arguments, 0, numberIndex),
operands = Array.prototype.splice.call(arguments, 0),
joiner = new Array(arguments.length);
for (var i = 0; i < numbers.length; i++) {
joiner[i*2] = numbers[i];
}
for (var i = 0; i < operands.length; i++) {
joiner[1+(i*2)] = operands[i];
}
var command = ("return (" + joiner.join('') + ");"),
execute = new Function(command);
console.log(command);
return execute();
}
console.log(executeMath(2, 3, 4, 5, "/", "+", "%"));