I built a simple Calculator using Javascript, but when I make operations such as 012 3 it always returns me 13 and not 15...!
Moreover, in my Calculator when I divide any number with 0 it returns me "Infinity" but I want to return "Error" or "It is not calculable" as string. What can I do in this case?
I spent a lot time in searching solutions here in StackOverflow because I noticed that this problem is very frequently, but I have not found a solution really adaptable for my code.
Here my code:
let output = document.getElementById('output');
let cells = Array.from(document.getElementsByClassName('cell'));
// console.log(cells);
cells.map(cell => {
cell.addEventListener('click', (e) => {
/* console.log('clicked');
console.log(e);
console.log(e.target);
console.log(e.target.innerText); */
switch (e.target.innerText) {
case 'C':
output.innerText = '';
break;
case '=':
// Funzione di gestione degli errori;
try {
output.innerText = eval(output.innerText);
} catch {
output.innerText = 'Error!';
}
break;
default:
output.innerText = e.target.innerText;
}
});
});
<div>
<div class="calculator">
<div id="output"></div>
<div class="buttons">
<button class="cell operator"> </button>
<button class="cell operator">*</button>
<button class="cell operator">/</button>
<button class="cell operator">-</button>
<button class="cell">7</button>
<button class="cell">8</button>
<button class="cell">9</button>
<button class="cell">4</button>
<button class="cell">5</button>
<button class="cell">6</button>
<button class="cell">1</button>
<button class="cell">2</button>
<button class="cell">3</button>
<button class="cell">0</button>
<button class="cell">.</button>
<button class="cell">C</button>
<button class="cell result">=</button>
</div>
</div>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
A working solution could be to remove leading 0 before eval.
let output = document.getElementById('output');
let cells = Array.from(document.getElementsByClassName('cell'));
// console.log(cells);
cells.map(cell => {
cell.addEventListener('click', (e) => {
/* console.log('clicked');
console.log(e);
console.log(e.target);
console.log(e.target.innerText); */
switch (e.target.innerText) {
case 'C':
output.innerText = '';
break;
case '=':
// Funzione di gestione degli errori;
try {
output.innerText = eval(output.innerText.replace(/^0 /, ''));
} catch {
output.innerText = 'Error!';
}
break;
default:
output.innerText = e.target.innerText;
}
});
});
<div>
<div class="calculator">
<div id="output"></div>
<div class="buttons">
<button class="cell operator"> </button>
<button class="cell operator">*</button>
<button class="cell operator">/</button>
<button class="cell operator">-</button>
<button class="cell">7</button>
<button class="cell">8</button>
<button class="cell">9</button>
<button class="cell">4</button>
<button class="cell">5</button>
<button class="cell">6</button>
<button class="cell">1</button>
<button class="cell">2</button>
<button class="cell">3</button>
<button class="cell">0</button>
<button class="cell">.</button>
<button class="cell">C</button>
<button class="cell result">=</button>
</div>
</div>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
I won't write your code for you but I'll point out where your issues are so you can continue. You have two different issues you've pointed out.
When you use "0" as the start of an integer in javascript it will be recognized as an octal or base 8 number, so "012" in base 8 might be something like 10 in decimal, adding 3 to that will equal 13. I don't know the exact details of this but you're going to struggle if you use integers starting with 0, so you have to make sure you remove any leading 0s from integers.
For your second issue a quick fix is to use
isFinite
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) to see if the division is infinity, however the proper solution would be to make sure you don't divide by zero or throw an exception.
You need to do some more string manipulation (like removing 0s) on output.innerText
before you can eval
it.
CodePudding user response:
Your solution is leveraging the eval() function. So you get the behavior of this function. If you try to enter the same operations in a Javascript console (try with your browser), you will have the same results.
As for the explanation about why 012 3 = 13: A leading 0 means the literal number will be octal (base 8). So 012 in base 10 is 8 2 = 10. 10 3 = 13.
Avoiding this will involve some much more complicated work.