I'm trying to get this function done but something is wrong, it should return 50 for a=5,b=10 or 2 for a=1,b=1. However any other way to write this function would be interesting
function getLargestExpressionResult(a, b) {
const sum = a + b;
const prod = a * b;
const diff = a - b;
const quot = a \ b;
let res = sum;
if (prod > res) res = prod;
if (diff > res) res = diff;
if (quot > res) res = quot;
return res;
}
enter code here
You can use Math.max(). It can take multiple parameters and gives you max.
Also for division it is /
function getLargestExpressionResult(a, b) {
const sum = a + b;
const prod = a * b;
const diff = a - b;
const quot = a / b;
return Math.max(sum,prod,diff,quot);
}
console.log(getLargestExpressionResult(5, 10))
You don't really need to find maximum element on your own, you can simply use Math.max:
const getLargestExpressionResult = (a, b) => Math.max(a * b, a / b, a + b, a - b);
console.log(getLargestExpressionResult(5, 10));
console.log(getLargestExpressionResult(1, 1));
Also should be noticed division is /, not \.
Or if you need to avoid Math usage:
getLargestExpressionResult = (a, b) => {
const expressionValues = [ a + b, a - b, a * b, a / b ];
let max = expressionValues[0];
for (const value of expressionValues) {
if (value > max) max = value;
}
return max;
}
console.log(getLargestExpressionResult(5, 10));
console.log(getLargestExpressionResult(1, 1));
Related
From the examples of big.js they show this example
0.3 - 0.1 // 0.19999999999999998
x = new Big(0.3)
x.minus(0.1) // "0.2"
x // "0.3"
x.div(y).plus(z).times(9).minus('1.234567801234567e+8').plus(976.54321).div('2598.11772')
Which is a very simple example. In my case I would like to calculate
res = a + (b / c) + (d + 1) / (e * f * g);
I cannot see how that can be calculated without introducing 7 temporary variables, which doesn't seam correct.
Question
Does anyone know how to calculate the above with big.js?
You can do this "inside-out", i.e. first convert the parts in the inner parentheses.
For example:
const temp1 = b.div(c),
temp2 = d.plus(1),
temp3 = e.times(f).times(g),
temp4 = temp2.div(temp3),
result = a.plus(temp1).plus(temp4);
But you don't actually need those temporary variables. Just take that last expression and inject the definition of the temporary variables, so your expression expands to this:
const res = a.plus(b.div(c)).plus(d.plus(1).div(e.times(f).times(g)));
// a + (b / c ) + (d + 1) / (e * f * g )
Demo:
const params = [1, 100, 5, 99, 2, 5, 2];
{ // First with native types:
const [a,b,c,d,e,f,g] = params;
const res = a + (b / c) + (d + 1) / (e * f * g);
console.log(res);
}
{ // Then with big.js
const [a,b,c,d,e,f,g] = params.map(Big);
const res = a.plus(b.div(c)).plus(d.plus(1).div(e.times(f).times(g)));
console.log(res.toNumber());
}
<script src='https://cdn.jsdelivr.net/npm/big.js#6.2.1/big.min.js'></script>
I cant seem to get my calculator to chain multiple operators together for example 5x5x5 should equal 125 but it just calculates 5x5 and will no longer calculate decimal numbers. Could anyone point me in the correct direction.
I have tried to assign the result to the firstNum but it seems to break the code.
button.forEach((button) =>
button.addEventListener('click', ()=> displayTotal(button.innerHTML)));
clearBtn.addEventListener('click', clear);
decmialBtn.addEventListener('click', appendDecimal);
functionBtn.forEach((button) =>
button.addEventListener('click', () => setOperator(button.innerHTML)));
equalsBtn.addEventListener('click', calculate)
let firstNum = "";
let secondNum = "";
let operatorSelection = "null";
let result = "";
function add(a, b){
return a + b
}
function subtract(a,b){
return a - b
}
function divide (a,b)
{
return a / b
}
function times (a,b){
return a*b
}
function operator(operator, numa, numb) {
switch(operator){
case '+':
return add(numa, numb);
break;
case '-':
return subtract(numa, numb);
break;
case '/':
return divide(numa,numb);
break;
case '*':
return times(numa,numb)
break;
}
}
function displayTotal (number){
userDisplay.value += number;
}
function clear (){
userDisplay.value = "";
}
function appendDecimal(){
userDisplay.value += ".";
}
function setOperator(operator){
firstNum = parseInt(userDisplay.value);
operatorSelection = operator;
result = firstNum;
clear()
}
function calculate(){
for (i = 0; i < 100; i++)
secondNum = parseInt(userDisplay.value);
result = operator(operatorSelection, firstNum, secondNum);
userDisplay.value = result;
[i];
}
For a simple JS calculator you could use the eval() function and it will handle all the operators for you taking PEMDAS in consideration, but you have to ensure the inpput is valid or it you won't work.
I have one on my Github if want an example:
https://github.com/gustavo-shigueo/calculator
Note: don't worry about the regexes I used, they are there just to prevent the user from typing stuff that would break the calculator
Here is an example of how I would do it:
operations = [
["*", (a, b) => +a * +b],
["/", (a, b) => +a / +b],
["+", (a, b) => +a + +b],
["-", (a, b) => +a - +b],
];
const calc = calcString => {
const split = [...calcString].reduce((prev, cur) => Number.isInteger(+cur) && Number.isInteger(+prev[prev.length - 1]) ? [...prev.slice(0, -1), prev[prev.length - 1] + cur] : [...prev, cur], [""]);
operations.forEach(([operator, funct]) => {
for (let i = 1; i < split.length - 1; i++) {
if (split[i] === operator) {
split[i - 1] = funct(split[i - 1], split[i + 1]);
split.splice(i, 2);
i--;
}
}
})
return split;
};
It doesn't support numbers with a dot/comma in them (e.g. 3.13) and no braces.
some explanation:
const split, I split the given string in numbers and operations, "3+45*4" would result in ["3", "+", "45", "*", "4"].
go over each operation in the given order to first do the "point calculation" and then + and -.
we go over the in 1. created array and look for our operation.
if we find one, we lool at the number before and after the operation and calculate the result given the 2 numbers and our operation type.
we overwrite those 3 elements with the result of our calculation.
we are done if all operations are done
I also have a more advanced version if you are interested
I am trying to find a simple way to perform a set of javascript math operations without using eval() function. Example: 1+2x3x400+32/2+3 and it must follow the PEMDAS math principle. This is what I have, but it doesn't work exactly it should.
function mdas(equation) {
let operations = ["*", "/", "+", "-"];
for (let outerCount = 0; outerCount < operations.length; outerCount++) {
for (let innerCount = 0; innerCount < equation.length; ) {
if (equation[innerCount] == operations[outerCount]) {
let operationResult = runOperation(equation[innerCount - 1], operations[outerCount], equation[innerCount + 1]);
var leftSideOfEquation = equation.substr(0, equation.indexOf(innerCount - 1));
var rightSideOfEquation = equation.substr(equation.indexOf(innerCount), equation.length);
var rightSideOfEquation = rightSideOfEquation.replace(rightSideOfEquation[0],String(operationResult));
equation = leftSideOfEquation + rightSideOfEquation;
innerCount = 0;
}
else {
innerCount++;
}
}
}
return "Here is it: " + equation; //result of the equation
}
If you don't want to use a complete library like mathjs - and you don't want to tackle creating your own script which would involve: lexical analysis, tokenization, syntax analysis, recursive tree parsing, compiling and output...
the simplest banal suggestion: Function
const calc = s => Function(`return(${s})`)();
console.log( calc("1+2*3*400+32/2+3") ); // 2420
console.log( calc("-3*-2") ); // 6
console.log( calc("-3 * + 1") ); // -3
console.log( calc("-3 + -1") ); // -4
console.log( calc("2 * (3 + 1)") ); // 8
My take at a custom MDAS
Here I created a Regex to retrieve operands and operators, accounting for negative values: /(-?[\d.]+)([*\/+-])?/g.
Firstly we need to remove any whitespace from our string using str.replace(/ /g , "")
Using JavaScript's String.prototype.matchAll() we can get a 2D array with all the matches as [[fullMatch, operand, operator], [.. ] we can than further flatten it using Array.prototype.flat()
Having that flattened array, we can now filter it using Array.prototype.filter() to remove the fullMatch -es returned by the regular expression and remove the last undefined value.
Define a calc Object with the needed operation functions
Iterate over the MDAS groups */ and than +- as regular expressions /\/*/ and /+-/
Consume finally the array of matches until only one array key is left
let str = "-1+2 * 3*+400+-32 /2+3.1"; // 2386.1
str = str.replace(/ +/g, ""); // Remove all spaces!
// Get operands and operators as array.
// Remove full matches and undefined values.
const m = [...str.matchAll(/(-?[\d.]+)([*\/+-])?/g)].flat().filter((x, i) => x && i % 3);
const calc = {
"*": (a, b) => a * b,
"/": (a, b) => a / b,
"+": (a, b) => a + b,
"-": (a, b) => a - b,
};
// Iterate by MDAS groups order (first */ and than +-)
[/[*\/]/, /[+-]/].forEach(expr => {
for (let i = 0; i < m.length; i += 2) {
let [a, x, b] = [m[i], m[i + 1], m[i + 2]];
x = expr.exec(x);
if (!x) continue;
m[i] = calc[x.input](parseFloat(a), parseFloat(b)); // calculate and insert
m.splice(i + 1, 2); // remove operator and operand
i -= 2; // rewind loop
}
});
// Get the last standing result
console.log(m[0]); // 2386.1
It's a little hacky, but you can try something like this:
var eqs = [
'1+2*3*4+1+1+3',
'1+2*3*400+32/2+3',
'-5+2',
'3*-2',
];
for(var eq in eqs) { console.log(mdas(eqs[eq])); }
function mdas(equation) {
console.log(equation);
var failsafe = 100;
var num = '(((?<=[*+-])-|^-)?[0-9.]+)';
var reg = new RegExp(num + '([*/])' + num);
while(m = reg.exec(equation)) {
var n = (m[3] == "*") ? m[1]*m[4] : m[1]/m[4];
equation = equation.replace(m[0], n);
if(failsafe--<0) { return 'failsafe'; }
}
var reg = new RegExp(num + '([+-])' + num);
while(m = reg.exec(equation)) {
var n = (m[3] == "+") ? 1*m[1] + 1*m[4] : m[1]-m[4];
equation = equation.replace(m[0], n);
if(failsafe--<0) { return 'failsafe'; }
}
return equation;
}
I want to create a random generator of math operations. I'm trying with ASCII codes but what happens is that it just concatenate the operands and operators as a String. Anyone has a suggestion for this?
let a = Math.floor(Math.random()*100)
let b = Math.floor(Math.random()*100)
let ascCode = Math.floor(Math.random()* (46 - 42)) + 42
let op = String.fromCharCode(ascCode)
let c = a + `${op}` + b;
console.log(c)
You can use eval:
The eval() function evaluates JavaScript code represented as a string.
let a = 1
let b = 2
let ascCode = Math.floor(Math.random()* (46 - 42)) + 42
let op = String.fromCharCode(ascCode)
let c = eval(a + `${op}` + b);
console.log(c)
But eval can be troublesome.
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.
eval() is also slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.
msdn
Another solution would be to use some if:
let a = 1
let b = 2
let ascCode = Math.floor(Math.random()* (46 - 42)) + 42
let op = String.fromCharCode(ascCode)
let c = 0;
if (op == "*")
c = a + b;
if (op == "+")
c = a + b;
if (op == "-")
c = a - b;
/*etc*/
console.log(c)
or even a map where keys are operators and values are functions:
let a = 1
let b = 2
let ascCode = Math.floor(Math.random()* (46 - 42)) + 42
let op = String.fromCharCode(ascCode)
let operators = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b, // handle zero!
'%': (a, b) => a % b // handle zero!
};
console.log(operators[op](a,b))
This solution is similar to things discussed in the comments. It is a different, non-eval way of generating random math operations:
const ops = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b,
'%': (a, b) => a % b,
'>': (a, b) => a > b,
'<': (a, b) => a < b,
// etc
}
const randomOperation = ((ops) => {
const keys = Object.keys(ops)
const randomOpKey = () => keys[Math.floor(Math.random() * keys.length)]
const evalOp = (key, a, b) => ops[key](a, b)
return () => {
const op = randomOpKey()
const a = Math.floor(Math.random() * 100)
const b = Math.floor(Math.random() * 100)
return {
expression: `${a} ${op} ${b}`,
result: evalOp(op, a, b)
}
}
})(ops)
// demo
for (let i = 0; i < 20; i++) {
let {expression, result} = randomOperation()
console.log(`${expression} = ${result}`)
}
Note that what randomOperation returns is objects with two properties: expression as a string, and result as a value, which will be numeric or boolean. The demo code shows one way to use it. You have to manually maintain the list of operations, which is different than with the eval solutions.
I don't know what better suits your needs, but this should show that there are reasonable non-eval solutions possible.
What you could use (though this is definitely not a good practice), is eval(), which evaluates a string as javascript code.
(Another word of warning, eval is evil and shouldn't be used in production)
let a = Math.floor(Math.random()*100)
let b = Math.floor(Math.random()*100)
let ascCode = Math.floor(Math.random()* (46 - 42)) + 42
let op = String.fromCharCode(ascCode)
let c = eval(a + `${op}` + b);
console.log(c)
You should use built-in function eval()
let operators = ['+','-','*','/','%'];
let number1 = 5;
let number2 = 4;
function getRandomOperation(){
let randOpeator = operators[Math.floor(Math.random() * operators.length)];
return eval(`${number1} ${randOpeator} ${number2}`);
}
console.log(getRandomOperation());
You should evalute expression, using javascript eval function. It expects string as input.
const result = eval(c);
console.log(result);
Reference
I presume it happens because you are using concatenation when one from concatenated values is a string:
let op = String.fromCharCode(ascCode)
To obtain a number under variable c you have to make sure that ${op} is number as well.
I want to be able to run the func n times with this createIterator function.
var createIterator = function (func, n) {
getDouble = function (x) {
return x + x;
};
return getDouble * n;
};
I want to be able to do this with the code:
var getQuad = createIterator(getDouble, 2);
getQuad(2) //8
Here are the tests is needs to pass:
Test.describe("Iterator for 'getDouble' function", function() {
var getDouble = function (n) {
return n + n;
};
Test.it("Running the iterator for once", function() {
var doubleIterator = createIterator(getDouble, 1);
Test.assertEquals(doubleIterator(3), 6, "Returns double of 3 as 6");
Test.assertEquals(doubleIterator(5), 10, "Returns double of 5 as 10");
});
Test.it("Running the iterator twice", function() {
var getQuadruple = createIterator(getDouble, 2);
Test.assertEquals(getQuadruple(2), 8, "Returns quadruple of 2 as 8");
Test.assertEquals(getQuadruple(5), 20, "Returns quadruple of 5 as 20");
});
});
I have been at this for awhile and have not been able to figure this out. Any help would be awesome. Thanks!
You can write a simple repeat procedure that when applied to n, f, and x, will repeat the application of function f to argument x, n times.
// ES6
const repeat = n => f => x =>
n === 1 ? f(x) : repeat(n-1)(f)(f(x));
const getDouble = x => x * 2;
const double = repeat(1)(getDouble);
const quad = repeat(2)(getDouble);
See it work
console.log(double(3)); // 6
console.log(double(5)); // 10
console.log(quad(2)); // 8
console.log(quad(5)); // 20
Let step through the evaluation of one of the examples:
const double = repeat(1)(getDouble);
Because repeat has been applied to n and f here, it returns
x => 1 === 1 ? getDouble(x) : repeat(0)(getDouble)(getDouble(x))
Now, when we call
double(3);
Substitute 3 for x
1 === 1 ? getDouble(3) : repeat(0)(getDouble)(getDouble(3));
Because 1 === 1, the first part of the ternary expression is returned
getDouble(3); // 6
Recap:
double(3) === getDouble(3) === 6
Now let's see the same process for quad
const quad = repeat(2)(getDouble);
Because repeat has been applied to n and f here, it returns
x => 2 === 1 ? getDouble(x) : repeat(1)(getDouble)(getDouble(x))
Now, when we call
quad(2);
Substitue 2 for x
2 === 1 ? getDouble(2) : repeat(1)(getDouble)(getDouble(2));
Because 2 === 1 is false, the second part of the ternary expression is returned
repeat(1)(getDouble)(getDouble(2))
repeat(1)(getDouble)(4)
So we have to call repeat again, with n=1, f=getDouble, x=4, so
1 === 1 ? getDouble(4) : repeat(0)(getDouble)(getDouble(4))
Because 1 === 1, the first part of the ternary expression is returned
getDouble(4); // 8
Recap:
quad(2) === getDouble(4) === 8
If you need the ES5, here you go
// ES5
var repeat = function repeat(n) {
return function (f) {
return function (x) {
return n === 1 ? f(x) : repeat(n - 1)(f)(f(x));
};
};
};
var getDouble = function getDouble(x) {
return x * 2;
};
var double = repeat(1)(getDouble);
var quad = repeat(2)(getDouble);
console.log(double(3)); // 6
console.log(double(5)); // 10
console.log(quad(2)); // 8
console.log(quad(5)); // 20
Lastly,
If you want your original API, which I believe to be inferior, we can still implement that
// ES6
const createIterator = (f, n) => x =>
n === 1 ? f(x) : createIterator(f, n-1)(f(x));
const getDouble = x => x * 2;
const double = createIterator(getDouble, 1);
const quad = createIterator(getDouble, 2);
And here's the ES5
// ES5
var createIterator = function createIterator(f, n) {
return function (x) {
return n === 1 ? f(x) : createIterator(f, n - 1)(f(x));
};
};
var getDouble = function getDouble(x) {
return x * 2;
};
var double = createIterator(getDouble, 1);
var quad = createIterator(getDouble, 2);
Both implementations work identically
So why is repeat(n)(f)(x) better ?
Well, because the function is fully curried, you can partially apply it in meaningful ways.
const getDouble = x => x * 2;
const once = repeat(1);
const twice = repeat(2);
const thrice = repeat(3);
const quad = twice(getDouble);
quad(5); // 20
const annoyingAlert = thrice(x => {alert(x); return x;});
annoyingAlert('wake up !'); // displays 'wake up !' three times
Your function isn't as flexible because it takes the function, f, and the number of times, n, as a tuple. Getting around this would require manually currying your function or using a Function.prototype.bind hack.
Try rearranging variables. Note, getDouble would be undefined at var getQuad = createIterator(getDouble, 2); as getDouble is defined within createIterator
var createIterator = function (func, n) {
getDouble = function (x) {
return (x + x) * n;
};
return func || getDouble;
};
var getQuad = createIterator(null, 2);
console.log(getQuad(2)) //8
alternatively
var createIterator = function(func, n) {
getDouble = function(x) {
return x + x;
};
return func.bind(null, n * n) || (getDouble(n)) * n;
};
var getQuad = createIterator(function(x) {
return x + x;
}, 2);
console.log(getQuad(2))
I just want to run getDouble n times.
You could use a loop inside of createIterator , return accumulated value as variable within function returned from createIterator that can be multiplied by parameter passed to getQuad
var createIterator = function(func, n) {
getDouble = function(x) {
return x + x;
};
var curr = n, res = 0;
while (--curr) {
res += func && func(n) || getDouble(n);
}
return function(y) {
return res * y
}
};
var getQuad = createIterator(null, 2);
console.log(getQuad(5)) // 20
You can do it like this,
Create an empty array of n
Fill the array by the function(arguments)
Join the array by operator
Create a function constructor using the joined array and arguments
Use the new function inside another function to pass the arguments from outside, and then return this new function.
Code snippet of what I am saying is here (if your browser supports Array.prototype.fill)
var createIterator = function (func, n, operator) {
operator = operator || "+";
var inner = Function(["f", "a"], "return " + Array(n ).fill("f(a)").join(operator) + ";");
return function (arg) {
return inner(func, arg);
};
};
var c = createIterator(function (n) {return n + n;}, 2);
document.write(c(3) + "<br/>");
document.write(c(6) + "<br/>");
var d = createIterator(function (n) {return n + n;}, 3, "+");
document.write(d(3) + "<br/>");
document.write(d(6) + "<br/>");
otherwise use this snippet
var createIterator = function (func, n, operator) {
operator = operator || "+";
var array = [];
for (var i = 0; i < n; i += 1) {array[i] = "f(a)";}
var inner = Function(["f", "a"], "return " + array.join(operator) + ";");
return function (arg) {
return inner(func, arg);
};
};
var c = createIterator(function (n) {return n + n;}, 2);
document.write(c(3) + "<br/>");
document.write(c(6) + "<br/>");
var d = createIterator(function (n) {return n + n;}, 3, "+");
document.write(d(3) + "<br/>");
document.write(d(6) + "<br/>");