eval() is not working - javascript

So I try build my own Javascript calculator as an exercise. Unfortunately when I try to use the eval() function with "=" button click to convert string into result, for example "2+2*2", nothing happens. Here's my code:
var draw = document.getElementById("result");
function calc(x) {
draw.innerHTML += x;
if (x === '=') {
draw.innerHTML = eval(draw.innerHTML);
} else if (x === 'c') {
draw.innerHTML = '0';
} else if (x === 'sqrt') {
draw.innerHTML = Math.sqrt(eval(draw.innerHTML));
} else if (x === 'pow') {
draw.innerHTML = Math.pow(eval(draw.innerHTML));
}
}

draw.innerHTML += x;
means if e.g. your string is 2*2 and you call
calc("sqrt")
the draws content will be
"2*2sqrt"
and thats not a valid expression, therefore the eval will fail. You may want to only concat if its not an operation:
function calc(x) {
if (x === '=') {
return draw.innerHTML = eval(draw.innerHTML);
} else if (x === 'c') {
return draw.innerHTML = '0';
} else if (x === 'sqrt') {
return draw.innerHTML = Math.sqrt(eval(draw.innerHTML));
} else if (x === 'pow') {
return draw.innerHTML = Math.pow(eval(draw.innerHTML),2);
}
draw.innerHTML += x;
}
That can be beautified with an object as a lookup table:
const result = n => eval(n),
sqrt = n => Math.sqrt(eval(n)),
pow = n => Math.pow(eval(n),2),
default = (n, add) => n + add;
function calc(in){
draw.innerHTML = ({"=":result, sqrt, pow}[in] || default)(draw.innerHTML, in);
}

Related

React Calculator: How to prevent multiple decimals in a number using Math-expression-evaluator?

As the title says I am using a math-expression library to do my calculations but I am having trouble figuring out the logic for decimals and how to prevent two decimals in one number inside an array. I have highlighted the part that is giving me trouble.
Here is my code sandbox link https://codesandbox.io/s/youthful-frost-2s6v6?file=/src/HookClaculator.js:181-2221
const [input, setInput] = useState([0]);
const [notANum, setNotANum] = useState("");
const [AC, setAC] = useState("");
const handleInputOneClick = (e) => {
let checkInput = input;
checkInput = [...checkInput, parseInt(e, 10)];
console.log(checkInput);
if (checkInput[1] !== 0) {
setInput([...input, parseInt(e, 10)]);
if (input.length > 23) {
console.log("exceeded 23");
setInput(["MAX DIGIT LIMIT REACHED"]);
setTimeout(() => {
setInput([0]);
}, 500);
}
}
};
const handleSymbolClick = (e) => {
if (Number.isInteger(input[input.length - 1])) {
setInput([...input, e]);
} else if (input[input.length - 1] === ".") {
setInput([...input, e]);
} else if (typeof input[input.length - 1] === "string") {
input.pop();
setInput([...input, e]);
}
};
const handleDecimalClick = (e) => {
if (input[input.length - 1] === ".") {
setInput([...input]);
} else if (isNaN(input[input.length - 1])) {
setInput([...input, e]);
} **else if (Number.isInteger(input[input.length - 1])) {
setInput([...input, e]);
}**
};
const handleEqualsClick = (e) => {
let exp = "";
if (input[0] === 0 && input.length <= 1) {
console.log("hell yeah");
setNotANum(["NaN"]);
} else if (input.length > 1) {
console.log("input length is " + input.length);
input.forEach((el) => {
return (exp += el);
});
let value = mexp.eval(exp);
setInput([value]);
}
};
const handleClickReset = (e) => {
setAC(e);
setInput([0]);
};
return (
<div id="calculator-div">
<HookDisplay input={input} notANum={notANum} AC={AC} />
<HookButtons
inputOneClick={handleInputOneClick}
symbolClick={handleSymbolClick}
decimalClick={handleDecimalClick}
handleEqualsButtonClick={handleEqualsClick}
handleClickReset={handleClickReset}
/>
</div>
);
};
return (
<div id="calculator-div">
<HookDisplay input={input} notANum={notANum} AC={AC} />
<HookButtons
inputOneClick={handleInputOneClick}
symbolClick={handleSymbolClick}
decimalClick={handleDecimalClick}
handleEqualsButtonClick={handleEqualsClick}
handleClickReset={handleClickReset}
/>
</div>
);
};
I think before pushing the decimal to the array you can ensure if it'll create a valid expression.
As currently the calculator supports basic operations, a number can never have more than one decimal and operands can only be one more than than the operators, leveraging the stated fact. This condition will work (inside handleDecimalClick):
let lastIndex = -1;
for (let i = input.length - 1; i >= 0; i--) {
if (input[i] === ".") {
lastIndex = i;
} else if (
input[i] === "+" ||
input[i] === "-" ||
input[i] === "*" ||
input[i] === "/"
) {
break;
}
}
if (lastIndex !== -1) return;
Also, for extra protection, added a regex to check if the expression is valid before it goes for evaluation (added the below lines in handleEquals):
const inp = input.join("");
const regex = /(?:(?:^|[-+_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-]?\d+)?\s*))+$/;
if (!regex.test(inp)) {
return;
}
I forked your codesandbox and added the fix.

simple calculator with javascript and it function calculator doesn't apply

I am new to Javascript so this is probably an easy fix but I cannot figure out. I am making a calculator using HTML, CSS and Javascript
and I pretty much only know about declaration, if/else statement, for/while loops and some basic elements of CSS and HTML.
here is my javascript code for the calculator.
var firstNum, operator, previousKey, previousNum;
const calculator = document.querySelector('.calculator');
const buttons = calculator.querySelector('.calculator__buttons');
const display = document.querySelector('.calculator__display');
function calculate(n1, operator, n2) {
let result = '';
if(operator === '+'){
result = n1 + n2;
}else if(operator === '-'){
result = n1 - n2;
}else if(operator === '*'){
result = n1 * n2;
}else if(operator === '/'){
result = n1 / n2;
}
return result;
}
buttons.addEventListener('click', function (event) {
const target = event.target;
const action = target.classList[0];
const buttonContent = target.textContent;
if (target.matches('button')) {
let firstNum = 0;
if (action === 'number') {
if (display.textContent > 0 ) {
display.textContent += buttonContent //
}
else {display.textContent = buttonContent}
//display.textContent = buttonContent
console.log('number1 ' + buttonContent + ' button1');
previousKey = 'number';
}
if (action === 'operator') {
console.log('operator1 ' + buttonContent + ' button1');
operator = buttonContent;
firstNum = display.textContent
//console.log(firstNum)
return firstNum
previousKey = 'operator';
}
if (action === 'decimal') {
// console.log('deciaml1');
previousKey = 'decimal';
}
if (action === 'clear') {
display.textContent = '0'
console.log('clear1');
previousKey = 'clear';
}
if (action === 'calculate') {
console.log('caculate1');
display.textContent = calculate(firstNum, operator, display.textContent)
previousKey = 'calculate';
}
}
});
although I set arithmetic operations above as function calculate(n1, operator, n2)
my caculator // here is what it looks like.
result of 5-9 comes out as -59.
I will appreciate if I could get some help.
thank you in advance.
The issue is that you are sending in strings to the calculate function. So you should explicitly convert the string textContent to integer values as such in your code:
if (action === 'calculate') {
console.log('caculate1');
display.textContent = calculate(parseInt(firstNum,10), operator, parseInt(display.textContent,10))
previousKey = 'calculate';
}

How do I input values for this function and output the power(of input values)

Code snippet:
Question: returns "undefined" on browser console,how do I get the code to input a and b and output power?
var a = 0;
var b = 0;
function power(a,b)
{
if (b === 0) {
console.log("power = 1");
} else if (b === 1) {
console.log("power = a");
} else {
return math.power(a, b-1);
}
console.log("Power");
}
did you call your function with required values? i.e
power(a,b);
var a = 0;
var b = 0;
function power(a,b)
{
if (b === 0) {
console.log("power = 1");
} else if (b === 1) {
console.log("power = a");
} else {
return math.power(a, b-1);
}
console.log("Power");
}
//call function
power(a,b);

Why my function return an array with only one element?

I am writing a function that will return an array with prime numbers.
The function should return an array with n elements. (n is a parameter) But it returns only one element. Why?
My codes:
function findPrimes(n)
{
var arr = [];
var currIndex = 0;
var sqrtNum;
var ceiledNum;
var ceiledIndex = 0;
var currCompose;
var res;
for (initNum = 2; arr.length < n; ++initNum)
{
sqrtNum = Math.sqrt(initNum);
ceiledNum = Math.ceil(sqrtNum);
for (currCompose = 2; currCompose <= ceiledNum; ++currCompose)
{
res = initNum % currCompose;
if (res == 0 && initNum != currCompose)
{
break;
}
else if (res == 0 && initNum == currCompose)
{
arr[currIndex] = initNum;
++currIndex;
break;
}
else if (res != 0 && initNum != currCompose)
{
continue;
}
else
{
console.log("Impossible result!");
}
}
}
return arr;
}
findPrimes(2); //return 2
findPrimes(10); //return 2 too
Jsbin
You should not be comparing initNum to currCompose. Keep in mind that initNum is the number you are checking (say, 71), and currCompose will be at most ceil(sqrt(initNum)) (say 9), so the two will never be equal.
Also note that it is best to append to the list and verify that no divisors where found only after the inner loop has finished.
This modified version works.
function findPrimes(n)
{
var arr = [];
var currIndex = 0;
var sqrtNum;
var ceiledNum;
var ceiledIndex = 0;
var currCompose;
var res;
var initNum;
for (initNum = 2; arr.length < n; ++initNum)
{
sqrtNum = Math.sqrt(initNum);
ceiledNum = Math.ceil(sqrtNum);
for (currCompose = 2; currCompose <= ceiledNum; ++currCompose)
{
res = initNum % currCompose;
if (res == 0 && initNum != currCompose)
{
break;
}
}
if (currCompose == ceiledNum+1)
{
arr[currIndex] = initNum;
++currIndex;
}
}
return arr;
}
var primes = findPrimes(6);
document.write(primes);
correct Line 14 of your code as follows and it works like charm.
for (currCompose = 2; currCompose <= initNum; ++currCompose)
function FindPrime(numbers){
if(numbers.constructor === Array){
output = [];
for (var i = numbers.length - 1; i >= 0; i--) {
if(isPrime(numbers[i]) == true){
output.push(numbers[i]);
};
};
return output;
}
}
function isPrime(numb){
if (numb % 2 == 0) return false;
for (var i=3; i<= Math.sqrt(numb); i = i + 2) {
if (numb % i == 0) {
return false;
}
}
return true;
}
numbers = [1,2,3,4,5];
test = FindPrime(numbers);
console.log('testing', test);

How do I remove the "reverse character order" function?

How do I remove the function in this code to reverse the order of the characters? All I would like this function to do is replace all vowels imputed with "er".
Here is the pastebin: http://pastebin.com/R9e0JRce
// JavaScript Document
function flip() {
var result = flipString(document.f.original.value);
document.f.flipped.value = result;
}
function flipString(aString) {
aString = aString.toLowerCase();
var last = aString.length - 1;
var result = "";
for (var i = last; i >= 0; --i) {
result += derpChar(aString.charAt(i))
}
return result;
}
function derpChar(c) {
if (c == 'a') {
return 'er'
}
else if (c == 'e') {
return 'er'
}
else if (c == 'i') {
return 'er'
}
else if (c == 'o') {
return 'er'
}
else if (c == 'u') {
return 'er'
}
return c;
}
If all you want to do is replace a set of characters, it could be done easily using a regular expression:
var str = 'abcdef';
var output = str.replace( /[aeiou]/g, 'er' );
result: erbcderf
more info here

Categories