You'll have to forgive me, I'm new to JavaScript...like a few weeks new. Anyway, I created a code using JavaScript to generate two random numbers, ask to add them, and give a "That is correct/that is incorrect" answer based on the users response. I wanted to add the other signs (-,*,/) to the equation and decided to try my hand at arrays to do so. Here is what I have so far:
<head>
<meta charset="utf-8" />
<title>Math Games</title>
</head>
<body>
<script>
var Answer;
var numbers=new Array();
var signs=new Array();
var Signs2=new Array();
var SignNoQuote=new Array();
numbers[0]=(Math.floor(Math.random() * 10 + 1));
numbers[1]=(Math.floor(Math.random() * 10 + 1));
signs[0]="+";
signs[1]="-";
signs[2]="*";
signs[3]="/";
SignNoQuote[0]="+";
SignNoQuote[1]="-";
SignNoQuote[2]="*";
SignNoQuote[3]="/";
Signs2[0]=(Math.floor(Math.random() * 4));
Answer=window.prompt("What is " + numbers[0] + signs[Signs2[0]] + numbers[1] + "?");
if(Answer==numbers[0] + SignNoQuote[Signs2[0]] + numbers[1])
{
window.alert("That's Correct!");
}
else
{
window.alert("That is Incorrect");
}
</script>
Refresh
</body>
It asks the question correctly, but when the right answer is given, it says that it is incorrect. I tried removing the quotation marks from the values of the "SignNoQuote" array hoping it would work, but when it is run that way, none of the script will run and the debugger claims it to be a syntax error? What am I doing wrong and how can I fix it?
If you want something specific to the use case you have, this will work nicely:
//A mapping from the symbol for an operation to
//the function that executes it.
var opFunction = {
"+": function (x, y) { return x + y; },
"-": function (x, y) { return x - y; },
"*": function (x, y) { return x * y; },
"/": function (x, y) { return x / y; }
};
//Gets the operation symbol.
var op = SignNoQuote[Signs2[0]];
//Looks up the function for the operation,
//then calls it with your numbers as operands.
var result = opFunction[op](numbers[0], numbers[1]);
However, if you need something general purpose for evaluating mathematical expressions, Brad's answer provides what you need.
If I'm understanding the problem, you are trying to use a string of a symbol to do math.
numbers[0] + SignNoQuote[Signs2[0]] + numbers[1]
The trouble with this is that + means concatenation when used in the context of strings. You don't have a + operator in code, you have the string of text with one character, +. These are fundamentally different. It's no different than this:
numbers[0] + '+' + numbers[1]
.... which results in something like this:
"1+2"
What you need to do is actually execute that input somehow, such as with eval(). Unfortunately, this is where you run into some scary security issues, allowing users to execute whatever they want. In some contexts this can be safe, but usually it isn't.
There are options for you to run this equation. See this question for details: Evaluating a string as a mathematical expression in JavaScript
When you're checking you're answer, you use a comparison to:
numbers[0] + SignNoQuote[Signs2[0]] + numbers[1]
But assuming you want it to multiply, what that actually is, is something like:
2 + "*" + 1
Which is not the same as:
2 * 1
The easiest way to do this would probably be with a if ... else if ... else if ... statement. Something like:
var answerCorrect = false;
if (SignNoQuote[Signs2[0]] == "+") {
answerCorrect = (Answer == numbers[0] + numbers[1]);
} else if (SignNoQuote[Signs2[0]] == "*") {
answerCorrect = (Answer == numbers[0] * numbers[1]);
} else if (etc ...
then:
if(answerCorrect) {
window.alert("That's Correct!");
} else {
window.alert("That is Incorrect");
}
Related
I'm making a calculator for a site project of mine where you can type your entire expression before resolving, for example: 2+3*4 would return 14, 22-4 would return 18, 20+5! would return 140, and so on.
And that works for simple expressions like the ones I showed, but when I add brackets the code breaks.
So a simple expression like (2+3)! that should return 120 actually returns 10 or 2+3!.
my original ideia to make even the basic 2+3! work was to separate the string in math simbols and the rest. so it would separate in this case it would separate it into 2, + and 3!; where it would find the symbol and resolve just that part. And that's why it solves 10 instead of not working.
But after trying to solve I couldn't make the code work except in a extremely specific situation, so I decided to redo the code and post this here in case someone could help me out.
This is the function that I'm currently using to prepare my string for evaluation:
function sepOperFat(){
//2+3! it's working
//1+(2-(2+2)+3)! want that to work in the end
var value = document.calculator.ans.value;
var operandoPos = ['0'];
var operandoInPos = [''];
var paraResolver = [];
for(i = 0; i <= value.length; i++){
//check if value[i] is equal to +, -, ×, ÷, * & /
if(value[i] == '+' || value[i] == '-' || value[i] == '×' || value[i] == '÷' || value[i] == '*' || value[i] == '/'){
operandoPos.push(i);
operandoInPos.push(value[i]);
}
}
paraResolver.push(value.slice(operandoPos[0], operandoPos[1]));
for(var total = 1; total <= operandoPos.length; total++){
paraResolver.push(value.slice(operandoPos[total] + 1, operandoPos[total + 1]));
}
document.calculator.ans.value = '';
for(var total = 0; total <= paraResolver.length - 2; total++){
if(paraResolver[total].includes('!')){
document.calculator.ans.value += "factorial(" + paraResolver[total] + ")";
}else{
document.calculator.ans.value += paraResolver[total];
}
document.calculator.ans.value += operandoInPos[total + 1];
}
}
document.calculator.ans.value is the name of the string where i have the expression.
operandoPos is the position on the string where a symbol is at.
operandoInPos is the symbol (I maybe could have used value.charAt(operandoPos) for that too).
paraResolver is the number that I will be solving (like 3).
factorial( is the name of my function responsible for making the number factorial.
the function doesn't have a return because I still want to solve inside the document.calculator.ans.value.
to resolve the equation I'm using document.calculator.ans.value = Function('"use strict"; return '+ document.calculator.ans.value)(); that activates when I press a button.
And yeah, that's it. I just want a function capable of knowing the difference between (2+3)! and 2+(3)! so it can return factorial(2+3) instead of (2+factorial(3)).
Thank you for your help.
Your biggest problem is going to be that order of operations says parentheses need to be evaluated first. This might mean your code has to change considerably to support whatever comes out of your parentheses parsing.
I don't think you want all of that handled for you, but an approach you can take to sorting out the parenthesis part is something like this:
function parseParentheses(input) {
let openParenCount = 0;
let myOpenParenIndex = 0;
let myEndParenIndex = 0;
const result = [];
for (let i = 0; i < input.length; i++) {
if (input[i] === '(') {
if (openParenCount === 0) {
myOpenParenIndex=i;
// checking if anything exists before this set of parentheses
if (i !== myEndParenIndex) {
result.push(input.substring(myEndParenIndex, i));
}
}
openParenCount++;
}
if (input[i] === ')') {
openParenCount--;
if (openParenCount === 0) {
myEndParenIndex=i+1;
// recurse the contents of the parentheses to search for nested ones
result.push(parseParentheses(input.substring(myOpenParenIndex+1, i)));
}
}
}
// capture anything after the last parentheses
if (input.length > myEndParenIndex) {
result.push(input.substring(myEndParenIndex, input.length));
}
return result;
}
// tests
console.log(JSON.stringify(parseParentheses('1!+20'))) // ["1!+20"]
console.log(JSON.stringify(parseParentheses('1-(2+2)!'))) // ["1-",["2+2"],"!"]
console.log(JSON.stringify(parseParentheses('(1-3)*(2+5)'))) // [["1-3"],"*",["2+5"]]
console.log(JSON.stringify(parseParentheses('1+(2-(3+4))'))) // ["1+",["2-",["3+4"]]]
this will wrap your input in an array, and essentially group anything wrapped in brackets into nested arrays.
I can further explain what's happening here, but you're not likely to want this specific code so much as the general idea of how you might approach unwrapping parenthesis.
It's worth noting, the code I've provided is barely functional and has no error handling, and will behave poorly if something like 1 - (2 + 3 or 1 - )2+3( is provided.
Ultimately I want to take this:
2x + 3 = 5
and solve for x, by first subtract 3 from both sides so 2x = 2, then divide both sides by 2 so x = 1. I was thinking a lot how one should go about making a function like this in JavaScript that can return an array of the steps done in order, including the result. Obviously "eval" wouldn't do anything for this, so seemingly one has to re-create equations.
I initially thought to first of all, ignore X, and just try to make a function that can solve simple equations, without eval or any built-in function.
I figured that the first step is to break up the terms using .split, but I was having some trouble with this, as I need to split for multiple symbols. For example, say I have the simple expression to evaluate: 3 - 6 * 3 / 9 + 5. So before we even get into order of operations, just splitting up each term (and categorizing them) is the hard part, which is the main concrete-question I have at this point.
I started simply splitting one after the other, but I was having some problems, and especially considering the order.
function solve(eq) {
var minuses = eq.split("-"),
pluses = minuses.map(x=> x.split("+")),
timeses = pluses.map(x=>x.map(y=>y.split("*"))),
dividers = timeses.map(x=>x.map(y=>y.map(z=>z.split("/"))));
console.log(minuses, pluses, timeses, dividers);
}
solve("3 - 6 * 3 / 9 + 5");
As you can see, for each successive operator I need to map through each of he elements of the previous one to split it, and then I am left with an array of arrays etc...
So 1) how can I split up these terms more efficiently, without making a new variable for each one, and manually recursively mapping through each one? Seemingly I should just have some kind of dictionary of array keeping track of orders of operations (not considering parenthesis or exponents now): ["*","/","+","-"] -- and given that array, generate something similar to the last array in the above example ("dividers") which contains only constants, and somehow keep track of the which elements each of the stored arrays follows...
and 2) How can I solve the expression given the arrays of values?
I was just a little confused with the logic, I guess I need to work up from the last array and solve the constants one at a time, keeping track of which operator is the current one, but I'm not sure how exactly.
While your problem doesn't require to construct, binary expression tree is a good way to brainstorm the logic to solve a math query.
So for the query 3 - 6 * 3 / 9 + 5, the representative binary expression tree is:
plus
|_minus
| |_3
| |_divide
| |_times
| | |_3
| | |_6
| |_9
|_5
to solve above tree, you recursively solve from the leaf level up to the root.
Again, you don't need to construct a tree. It just helps us to see the logic of parsing here:
Get the last minus or plus expression in query and solve left and right child of that expression.
If no plus/minus, get the last times/division expression and solve left and right child
If meet a number, return that number value.
Given above logic, here is an implementation:
function solve(str) {
var expressionIndex = Math.max(str.lastIndexOf("-"), str.lastIndexOf("+"));
if (expressionIndex === -1) {
expressionIndex = Math.max(str.lastIndexOf("*"), str.lastIndexOf("/"));
}
if (expressionIndex === -1) {
var num = Number.parseInt(str.trim());
if (isNaN(num)) {
throw Exception("not a valid number");
} else {
return num;
}
} else {
var leftVal = solve(str.substring(0, expressionIndex).trim());
var rightVal = solve(str.substring(expressionIndex + 1).trim());
switch (str[expressionIndex]) {
case "+":
return leftVal + rightVal;
case "-":
return leftVal - rightVal;
case "*":
return leftVal * rightVal;
case "/":
return leftVal / rightVal;
}
}
}
function parse(str) {
var expressionIndex = Math.max(str.lastIndexOf("-"), str.lastIndexOf("+"));
if (expressionIndex === -1) {
expressionIndex = Math.max(str.lastIndexOf("*"), str.lastIndexOf("/"));
}
if (expressionIndex === -1) {
var num = Number.parseInt(str.trim());
if (isNaN(num)) {
throw Exception("not a valid number");
} else {
return { type: "number", value: num };
}
} else {
var leftNode = parse(str.substring(0, expressionIndex).trim());
var rightNode = parse(str.substring(expressionIndex + 1).trim());
return {
type: "expression",
value: str[expressionIndex],
left: leftNode,
right: rightNode
};
}
}
console.log(solve("3 - 6 * 3 / 9 + 5"));
console.log(parse("3 - 6 * 3 / 9 + 5"));
Above is a solution for very simple query with only +, -, *, / (no parenthesis, e.g.). For solving a equation like your first example requires a lot more of work.
EDIT: add a parse function to return the tree.
You can do that in following steps:
First of all use split() and split by the + and - which will occur after multiplication and division.
Then use map() on array and split() it again by * and /.
Now we have a function which will which will evaluate an array of numbers with operators to single number.
Pass the nested array to complete multiplication and division.
Then pass that result again to sovleSingle and perform addition and subtraction.
The function works same as eval as long as there are no brackets ().
Note: This doesnot matters the which occurs first among + and - or which occurs first among * and /. But *,/ should occur before +,-
function solveSingle(arr){
arr = arr.slice();
while(arr.length-1){
if(arr[1] === '*') arr[0] = arr[0] * arr[2]
if(arr[1] === '-') arr[0] = arr[0] - arr[2]
if(arr[1] === '+') arr[0] = +arr[0] + (+arr[2])
if(arr[1] === '/') arr[0] = arr[0] / arr[2]
arr.splice(1,1);
arr.splice(1,1);
}
return arr[0];
}
function solve(eq) {
let res = eq.split(/(\+|-)/g).map(x => x.trim().split(/(\*|\/)/g).map(a => a.trim()));
res = res.map(x => solveSingle(x)); //evaluating nested * and / operations.
return solveSingle(res) //at last evaluating + and -
}
console.log(solve("3 - 6 * 3 / 9 + 5")); //6
console.log(eval("3 - 6 * 3 / 9 + 5")) //6
I have set a number variable under c. After running it through local storage and a couple functions, the variable has turned into a string. Instead of x adding to c , x adds a digit to c. Can anyone see the problem?
function hi() {
c += x;
document.getElementById("paragraph").textContent = "This is a string" + c;
localStorage.clocal = c;
}
function resetvar() {
c = localStorage.clocal;
}
function bla() {
if (localStorage.getItem("clocal") === "null") {
document.getElementById("parargraph").textContent = "This Works Okay";
} else {
document.getElementById("parargraph").textContent = "This is a string" + localStorage.credits;
}
}
the data put in localStorage always as string.
If you wanna to get as number that you have to parse it
like this
c = parseInt(localStorage.clocal);
That's the nature of JS. You can use parseInt(c, 10) + x or x + 1 * c to over come this.
It's a little bit difficult to follow the flow of these methods, but one glaring issue I see is this line:
c += x
In this situation, you're saying that you want to set c equal to the result of c + x where x is a string, instead of setting x equal to x + c? By making this assignment, you are converting c to a string. Then after that point is doesn't matter what else you do -- it will still be a string unless you re-assign it explicitly as an integer.
I hope I understand your intention correctly.. It is a bit unclear.
I'm starting to learn javascript and I basically needed a countup that adds an x value to a number(which is 0) every 1 second. I adapted a few codes I found on the web and came up with this:
var d=0;
var delay=1000;
var y=750;
function countup() {
document.getElementById('burgers').firstChild.nodeValue=y+d;
d+=y;
setTimeout(function(){countup()},delay);
}
if(window.addEventListener){
window.addEventListener('load',countup,false);
}
else {
if(window.attachEvent){
window.attachEvent('onload',countup);
}
}
There's probably residual code there but it works as intended.
Now my next step was to divide the resultant string every 3 digits using a "," - basically 1050503 would become 1,050,503.
This is what I found and adapted from my research:
"number".match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
I just can't find a way to incorporate this code into the other. What should I use to replace the "number" part of this code?
The answer might be obvious but I've tried everything I knew without sucess.
Thanks in advance!
To use your match statement, you need to convert your number to a String.
Let's say you have 1234567.
var a = 1234567;
a = a + ""; //converts to string
alert(a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(","));
If you wish, you can wrap this into a function:
function baz(a) {
a = a + "";
return a.match(/.{1,3}(?=(.{3})+(?!.))|.{1,3}$/g).join(",");
}
Usage is baz(1234); and will return a string for y our.
While I do commend you for using a pattern matching algorithm, this would probably be easier to, practically speaking, implement using a basic string parsing function, as it doesn't look anywhere as intimidating from just looking at the match statement.
function foo(bar) {
charbar = (""+bar).split(""); //convert to a String
output = "";
for(x = 0; x < charbar.length; x++) { //work backwards from end of string
i = charbar.length - 1 - x; //our index
output = charbar[i] + output; //pre-pend the character to the output
if(x%3 == 2 && i > 0) { //every 3rd, we stick in a comma, except if it is not the leftmost digit
output = ',' + output;
}
}
return output;
}
Usage is basically foo(1234); which yields 1,234.
I'm trying to make a simple addition tool to add 2 values together, I'm just having a little trouble with the NaN checking... would like to print "Please insert numbers only" if either A or B, or both are NaN.
function getTotal() {
var a = parseInt(document.addBoxes.boxA.value);
var b = parseInt(document.addBoxes.boxB.value);
if (total != NaN) {
total = a+b;
document.getElementById("total").innerHTML = "The sum is " + total + ".";
}
else if (a === NaN || b === NaN){
document.getElementById("total").innerHTML = "Please insert numbers only.";
}
else if (a === NaN && b === NaN){
document.getElementById("total").innerHTML = "Please insert numbers only.";
}
};
Also, if there is a performance-friendly way to do this, or a better method.
Thanks!
Checking each individual value for NaN is not required.
function getTotal() {
var a = parseInt(document.addBoxes.boxA.value);
var b = parseInt(document.addBoxes.boxB.value);
var total = a + b;
if (!isNaN(total)) {
document.getElementById("total").innerHTML = "The sum is " + total + ".";
} else {
document.getElementById("total").innerHTML = "Please insert numbers only.";
}
}
Several problems in your code.
Line 4: if (total != NaN) {
total hasn't been defined yet. You should define it in a var beforehand if you don't want to leak globals.
var total = a + b;
Also, NaN will never equal itself so this kind of equality is dangerous. Either use the built-in isNaN() function to check for NaN or (since you mentioned performance-friendly) you can skip the function invocation and use:
if (total !== total) {
Since NaN is the only thing in javascript that doesn't equal itself. Notice I'm using a strict not-equals, we don't want any coercion. This might be a bit too abstract and people who look at the code later (including yourself) might have forgotten this unique property of NaN so I'd prefix this conditional with a comment and perhaps a link to the MDN - Necessity of isNaN page.
Your code might end up looking something like simonzack's answer.