JavaScript adding additional actions after receiving the result - javascript

I'm making a calculator in JS that displays commands and the result in a prompt.
I want to add an action that, after receiving the result of the operation, makes it possible to multiply, divide, etc. by another number.
Action plan: First action... = result > choose selector ( +, -, *,/) > choose second number > result --- and so on until you stop pressing enter with a blank field.
I was thinking of starting with a while loop to add the ability to choose a character but I don't know if it will affect the result of the previous action, additionally I don't know how to add the ability to choose the next number
switch (operator) {
case '+':
alert(numb1 + numb2)
break
case '-':
alert(numb1 - numb2)
break
case '*':
alert(numb1 * numb2)
break
case '/':
alert(numb1 / numb2)
break
case '%':
alert(numb1 % numb2)
break
}
while (true) {
let result = +prompt('Enter an arithmetic operator or leave blank.')
if (!result) break
}
}

Yes you can use while loop with a new param to get the new value input with prompt, such that:
while (true) {
let result = +prompt('Enter an arithmetic operator or leave blank.')
if (!result) break
let newNumber = +prompt('Enter a new number')
// do the arithmetic operation
}
Additionally, the operation in switch seems to be quite redundant. i.e.: one case for alert in one character / operator change.
You might want to use eval() for the operation.
let numb1 = 1 // original number
while (true) {
let result = prompt('Enter an arithmetic operator or leave blank.')
if (!result) break
let newNumber = prompt('Enter a new number')
// do the arithmetic operation
// if numb1 = 1, new Number = 2, result = '+', it will show '1 + 2'
alert(`${numb1} ${result} ${newNumber}`)
// numb1 = 3
numb1 = eval(`${numb1} ${result} ${newNumber}`)
}
For converting string to operation, please refer to this answer:
https://stackoverflow.com/a/26551015/9067107

This seens like a learning exercise, so I'll try to explain some thought before showing some code.
Your switch case assumes num1 and num2 are already known, but what you described says that num2 will only come after the operator.
Also, you want that math being done inside the loop, else it will only run once.
What you want is:
type first number;
type operator;
type next number;
show result = first/old number (operator) next/last number input;
type operator;
type next number;
show result = first/old number (operator) next/last number input;
... and so on until the "end command" is input.
We have to respect that order, so we'll need to store results and actions. This way we can keep the loop "alive".
Another thing, to be a "good loop", it has to start and end with the same actions.
So, we'll leave the first number input out of the loop, that way it will be something liek this:
ask "first number"
ask "operator" -> (end?) -> ask "next number" -> store and show "result"
ask "operator" -> (end?) -> ask "next number" -> store and show "result"
... and so on ...
// start prompting the user for the first number.
let oldNum = +prompt("first number: ");
let continue = true; // this is the condition to continue or end our loop.
while(continue) {
// prompt the user for the operator
let op = prompt('operator: ');
if (!(op === "+" || op === "-" || op === "/" || op === "*")) break;
// if anything aside from the expected inputs, the loop breaks.
let num = prompt('next number: ');
switch(op) {
case '+':
oldNum += num; // we add the new value to the old one.
break;
case '-':
oldNum -= num;
break;
case '/':
oldNum /= num;
break;
case '*':
oldNum *= num;
break;
}
// show result to user
alert(oldNum);
}
BTW, there are better ways to write this particular code, tried to make it similar to what you shown.

Related

trying to use switch with if else statement to make operations. but but syntax error appears?

i am a javascript beginner , tried to make a program to insert two inputs of numbers and insert an operator to make a mathematical function and make an alert if the input is not correct. i don't know why a syntax error appears after case + and doesn't work .is there other way to make the program?
any suggetions?
thanks in advance
There are a few different issues with your code and I'll go over them one by one:
First, note that typeof for first_number and second_number will be number regardless of the input. You want to check for NaN instead using the isNaN function.
Second, you will want to wrap the cases of the switch statement in curly braces.
Third, the case values themselves should be in quotes in this case.
Fourth, you will want the break keyword after each of your cases to prevent them from falling through to the next case. There are valid use cases for that (such as multiple cases with the same block) but it's not what you want in this basic example.
All in all, your code should look like this, basically:
var first_number = parseInt(prompt("Please enter a number"));
var second_number = parseInt(prompt("Please enter a number"));
if (isNaN(first_number) || isNaN(second_number))
{
alert("Please enter valid numbers.");
}
var operator = prompt("Please enter an operator");
var result;
switch(operator)
{
case "+":
result = first_number + second_number;
break;
case "-":
result = first_number - second_number;
break;
case "*":
result = first_number * second_number;
break;
case "/":
result = first_number / second_number;
break;
default:
result = "Invalid operator.";
break;
}
alert(result);
Lastly, please post your actual code in the contents of the post in future instead of an image.

Javascript: Convert string to computable

please someone help me about my javascript code. I want to convert string to be computable.
Example:
var string = "34.5 + 30";
the javascript function or code will automatically compute my string value. So the result will be 64.5 with a float or decimal data type.
hope someone can answer my query.
Use eval function.
Reference
The eval() function evaluates JavaScript code represented as a string.
But there is a security issue in this.
Executing JavaScript from a string is an enormous security risk. It is
far too easy for a bad actor to run arbitrary code when you use
eval(). See Never use eval()!, below.
var myString = "34.5 + 30";
console.log(eval(myString));
Since eval has some security issues, its always adviced not to use it. You could either make use of some custom libraries or implement your own parsing logic.
Please find a small paring logic from my side.
Please note, this evaluates the mathematical expressions linearly. This doesnot works with BODMAS rule or will not evaluate any complex expression. This is to evaluate a mathematical expression that contains only numbers, and basic operators such as +, -, * and /. If you wish to have custom validations you could build on top of this or can implement a solution of your own.
I have added the description as code comment
const myString = "34.5 + 30";
// Regex to split the expression on +, -, *, / and spaces
const isNumeric = /(?=[-+*\/(\s+)])/;
// Valid operators
const operators = ['+', '-', '*', '/'];
// Split the string into array
const expressionArray = myString.split(isNumeric);
// Object to hold the result and the operator while parsing the array generated
const result = { result: 0, operator: '' };
// loop though each node in the array
// If an operator is found, set it to result.operator
// If not an operator, it will be a number
// Check an operator is already existing in result.operator
// If then perform the operation with the current node and result and clear the result.operator
expressionArray.forEach((node) => {
const trimmedNode = node.trim();
if (trimmedNode) {
if (operators.indexOf(trimmedNode) === -1) {
if (result.operator) {
switch (result.operator) {
case '+':
result.result += Number(node);
break;
case '-':
result.result -= Number(node);
break;
case '*':
result.result *= Number(node);
break;
case '/':
result.result /= Number(node);
break;
result.operator = '';
}
} else {
result.result += Number(node);
}
} else {
result.operator = trimmedNode;
}
}
});
console.log(result.result);

Building a JavaScript Calculator from scratch?

I am trying to build a JavaScript calculator from scratch, without following a tutorial, as a learning exercise. Much of the functionality is working, except if a calculation is performed right after another. ie:
7 x 6 + 42
In that case, it resets the display to 0 but seems to keep the variable anyways.
Is it necessary to store the numbers in 3 values, instead of 2? Currently I'm using:
-currentValue, which holds the previous total of the calculation.
-newValue, which is the number the user is currently entering.
function newNum(pressed) { //Adds digit of key pressed to new number being entered.
//console.log ("Button pressed " + pressed);
if (newValue == 0) { //If new calculation, newValue is set to key pressed.
newValue += pressed;
} else { //Else if continuing calculation, key pressed is added to end of newValue.
newValue = newValue.toString();
newValue = newValue + pressed; //Adds digit at end of String, then converts back to Number.
newValue = parseFloat(newValue);
}
document.getElementById('result').innerHTML = newValue;
}
function newCalc(pressed) { //Will use this mathematical operation to find the value.
if (!currentValue) {
currentValue = newValue;
} else {
document.getElementById('result').innerHTML = newValue;
}
newOperation = pressed;
newValue = 0;
}
function equals() { //Resolves calculation.
newValue = parseFloat(newValue);
switch(newOperation) {
case "/":
currentValue = (currentValue / newValue);
break;
case "*":
currentValue = (currentValue * newValue);
break;
case "-":
currentValue = (currentValue - newValue);
break;
case "+":
currentValue = (currentValue + newValue);
break;
}
currentValue = parseFloat(currentValue);
newValue = 0;
document.getElementById('result').innerHTML = currentValue;
}
https://codepen.io/adam_weiler/pen/aRNppX
I'm still learning and I know the code is a bit bloated. Any suggestions how to streamline it would be helpful too!
EDIT: I gave a bad example. I'm just coding a basic calculator, where you tap buttons to enter numbers. It doesn't use BEDMAS; the order of operations is "the order the user inputs them". So yeah, just a basic tapping calculator.
If you input
7 | x | 8 | = | + | 5 | = |
it works without problems. I guess you want to execute equals() whenever an operation button is pressed, not only on =...
Is it necessary to store the numbers in 3 values, instead of 2?
No you don't have to. The trick is to perform one operation after another so you always work with only two values:
7
7 x
7 x 8
7 x 8 +
46 + // merged
46 + 5
46 + 5 =
51 // merged
In your example, the code tries to calculate the 7*6 and the 6+42 at the same time, but there is no 6 which can be added to the 42 because it was multiplied by 7, so it can't be calculated with. You should make rules to the operation preference, when there is a multiplying or a dividing the sorrounding numbers should be calculated as the new number and then you can operate further with your adding or substracting. Also, you should define the left-to-right rule as well, so if you have 2*3/4 then the error won't occur again.

Evaluate dynamically user-added If-Statements

How can I achieve that users can add multiply custom if-statements?
For example let's say there is a given variable called x with a given value of let's say 8.
The user sees that x = 8 and has a button to add an if-statement. He clicks the button and can insert the condition which triggers an event (let's say it prints "Hello World"). So he enters "x < 100" into the field which is true. Therefore "Hello World" is printed.
After clicking the button once again, he is able to add an other condition, let's say "x < 7" which is also true. Because both conditions are true, "Hello World" is still printed.
I think you got the point of my questions, even though I lack the vocabulary.
So how could I manage to let user add an undefined amount of conditions which will be checked before "Hello World" is printed?
The only solution I know is to limit the possible amount of conditions and check each one if it is empty / what the conditions says.
Thanks a lot!
Unless you want to build an entire language you have to get clear on what exact operations you are going to allow here.
For example the operation of < and > and ==, basically all comparison operations (<= and >= as well) can be implemented via the following:
/* your X variable, might be var if you desire to change */
let x = 12
/* the array of conditions the user entered */
var conditions : [(((Int, Int) -> Bool), Int)] = []
/* some user input - read as e.g. "x > 2"*/
conditions.append((<, 100))
conditions.append((>, 2))
conditions.append((==, 12))
/* you evaluate all conditions in the following way */
let eval = conditions.map { $0(x, $1) }
let allTrue = !eval.contains(false)
/* allTrue would be true in this case because 12 < 100 && 12 > 2 && 12 == 12 */
Your "hard" job is it now to interpret the user input as some condition. But that is not too difficult, you simply need a mapping of the text input of "<" to the actual operator <.
You can adjust the above code to take care of Double instead of Int easily if you fell like you need that. But you have to aware of floating point inaccuracy and the problem that arise when checking for equality (thanks to #dfri for pointing this out).
A little bit more difficult part comes in regards to combining the conditions with or instead of and what above code does and what you currently describe in your question.
Just because I like closures: The following is the entire input reading and parsing:
func getOperator(str: String) -> ((Int, Int) -> Bool)? {
switch str {
case "<":
return (<)
case ">":
return (>)
case "==":
return (==)
case "<=":
return (<=)
case ">=":
return (>=)
default:
return nil
}
}
func parseUserInput(str:String) -> (((Int, Int) -> Bool), Int) {
var input = str as NSString
input = input.stringByReplacingOccurrencesOfString(" ", withString: "")
//let variable = input.substringToIndex(1) // in case you want more than one variable, but that will have to change the entire setup a bit
// this has to be this "ugly" to incorporate both 1 char and 2 char long operators
let operato = input.substringFromIndex(1).stringByTrimmingCharactersInSet(NSCharacterSet.alphanumericCharacterSet())
let number = input.substringFromIndex(operato.lengthOfBytesUsingEncoding(NSASCIIStringEncoding) + 1)
if let number = Int(number), op = getOperator(operato) {
return (op, number)
}
return ((<, 999999)) // need some error handling here
}
conditions.append(parseUserInput("x > 123"))
Instead of resolving the operator using a function you can even use a plain old dictionary mapping from ">" to (>) etc.
First you need a way to switch between operators. A very simple enum is perfect for this. Just add all the operators you want to use.
enum Operator : String {
case biggerThan = ">"
case smallerThan = "<"
case equal = "=="
init?(string:String) {
switch string {
case ">" :
self = .biggerThan
case "<" :
self = .smallerThan
case "==" :
self = .equal
default :
return nil
}
}
}
Each time a user clicks a button and inserts a condition, a corresponding Condition value will be created.
struct Condition {
var value: Int
var operation: Operator
}
This function returns a Bool depending on x, the inputValue and the chosen operator.
func checkCondition(x: Int, condition: Condition) -> Bool {
switch condition.operation {
case .biggerThan :
return condition.value > x
case .smallerThan :
return condition.value < x
case .equal :
return condition.value == x
}
}
This does the same but for a whole bunch of conditions. Here you can implement more logic. If all need to be true for example add : if !result { return false }.
func checkAllConditions(x:Int, conditions: [Condition]) {
for condition in conditions {
let result = checkCondition(x, condition: condition)
print(result)
}
}
Now all you need to do is store conditions in an array as the user creates them
func userCondition(operation:String, input:String) -> Condition? {
guard let op = Operator(string: operation) else {
return nil
}
guard let doubleValue = Double(input) else {
return nil
}
return Condition(value: Int(doubleValue), operation: op)
}
let conditionA = userCondition("<", input: "10")! // use if let instead of !
let conditionB = userCondition(">", input: "10")! // use if let instead of !
let conditionC = userCondition("==", input: "23")! // use if let instead of !
var x : Int = 23
checkAllConditions(x, conditions: [conditionA,conditionB,conditionC])
struct MyConditions {
let myEps: Double = 0.001
var x: Double
var lessThan = [Double]()
var equalTo = [Double]()
var greaterThan = [Double]()
init(x: Double) {
self.x = x
}
mutating func addConstraint(operand: Double, op: String) {
if op == "<" {
lessThan.append(operand)
}
else if op == "==" {
equalTo.append(operand)
}
else if op == ">" {
greaterThan.append(operand)
}
}
func checkConstraints() -> Bool {
for op in lessThan {
if !(x < op) {
return false
}
}
for op in equalTo {
if !(x - myEps < op && x + myEps > op) {
return false
}
}
for op in greaterThan {
if !(x > op) {
return false
}
}
return true
}
}
Tests:
func feasibleHelloWorld(x: MyConditions) {
if x.checkConstraints() {
print("Hello world!")
}
}
var x = MyConditions(x: 8)
x.addConstraint(100, op: "<")
x.checkConstraints() // true
feasibleHelloWorld(x) // Hello world!
x.addConstraint(8, op: "==")
x.checkConstraints() // true
feasibleHelloWorld(x) // Hello world!
x.addConstraint(7, op: "<")
x.checkConstraints() // false
feasibleHelloWorld(x) // ... nothing

Replace with the regular expression

What regular expression I need to use to correct
if (text.indexOf("+") != -1) {
action = "+";
} else if (text.indexOf("-") != -1) {
action = "-";
} else if (text.indexOf("*") != -1) {
action = "*";
} else if (text.indexOf("/") != -1) {
action = "/";
}
this code
?
EDIT:
and how can I improve this code:
switch (action) {
case "+":
result = parseInt(array[0]) + parseInt(array[1]);
break;
case "-":
result = parseInt(array[0]) - parseInt(array[1]);
break;
case "*":
result = parseInt(array[0]) * parseInt(array[1]);
break;
case "/":
result = parseInt(array[0]) / parseInt(array[1]);
break;
default:
break;
}
Sorry for dull questions I am new in js.
You can use either of these:
var action = text.replace(/.*([+*/-]).*/,'$1');
var match = /[*+/-]/.exec(text);
var action = match && match[0];
If there's the possibility of newlines in your text then change the first to:
var action = text.replace(/[\d\D]*([+*/-])[\d\D]*/,'$1');
Edit: You can improve your switch statement by using, e.g.
// allow floating point values, and also
// don't accidentally interpret "011" as octal
array[0]*1 + array[1]*1;
For more details on why parseInt is probably bad, see this answer.
You can also remove the superfluous default section of your case statement. However, I suspect that your desired "improvement" was making fewer lines. Given that =-*/ are operators in JavaScript (and not methods), I cannot think of any way to avoid having four calculations (i.e. a switch or if/else if).
Whereas in Ruby you could, for example, use array[0].send(action,array[1]) to cover all four cases ;)

Categories

Resources