-2

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>
David
  • 208,112
  • 36
  • 198
  • 279
Valentina
  • 3
  • 3
  • 2
    0 means octal system in prefix, 10 + 3 = 13. – RatajS Nov 01 '21 at 13:36
  • Just check if the result [is finite](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite). – Teemu Nov 01 '21 at 13:37
  • I thought `eval` is not recommended to be used as it creates some security issues – Rana Nov 01 '21 at 13:48
  • I would avoid using eval, as long as this is a closed project that runs on a internal network... https://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil and https://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea – Gabriel Nov 01 '21 at 13:48

3 Answers3

0

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>
bZezzz
  • 972
  • 9
  • 22
0

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.

0

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

1 * 8^1 + 2 * 8^0 = 8 + 2 = 10

In base 10, 10 + 3 = 13, obviously.

Avoiding this will involve some much more complicated work. Even if you could easily get rid of leading zeroes, you will not have fixed the Infinity problem. There are other values that could be returned as well, for instance 0/0 returns NaN.

And also, beware of eval() potential security issues.

See: https://stackoverflow.com/a/18208029/9658671

Laurent Gabiot
  • 1,251
  • 9
  • 15