Add two array values and transform into a single Javascript variable

Asked

Viewed 122 times

4

I’m a beginner and still in the saga of building a calculator. I can’t use it() I don’t know if it was the right choice but I used array to store the numbers, I’ve tried to use a third array to get the results using push, but the value that shows me whether the result variable is an array or not is not correct, so I don’t know exactly where I went wrong.

let tela = document.getElementById('visor');
let nums = [];
let oldnum = [];
let operation;
let result = 0;

function mostranum(num) {
  tela.innerHTML += num;
  nums.push(Number(num));
  console.log(nums)


}

function limpa() {
  nums.pop();
  tela.innerHTML = nums;

}

function operator(ope) {
  if (nums.length > 8) {
    nums.length = 8;
  }


  if (oldnum.length == 0) { // quer dizer que é a primeira operação
    oldnum = nums;
    console.log(`old num recebeu ${oldnum}`);
    //console.log(typeof nums)
    operation = ope;
    nums.splice(0);
    tela.innerHTML = '';


  } else if (oldnum.length != 0 && ope != 'result') {
    // executar a operação anterior
    oldnum = calcula(oldnum, nums, operation);
    console.log(`resultado ${oldnum}`);
    console.log(typeof oldnum);
  }
}


function calcula(num1, num2, oper) {
  for (let c = 0; c < num1.length; c++) {
    switch (oper) {
      case 'sum':
        result += num1[c] + num2[c];
        //result.push(parseInt(num1[c]) + parseInt(num2[c]));
        break;
      case 'subtract':
        result = num1 - num2;
        break;
      case 'multiplication':
        result = num1 * num2;
        break;
      case 'division':
        result = num1 / num2;
        break;
    }
  }
  return result;

}
body{
    margin: 0;
    background-color: #d44b57;
}

#calculadora{
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    width: 350px;
    align-items: center;
    align-content: center;
    margin: auto;

}

button{
    border: 0;
    background: #9d0229;
    color: #ffffff;
    cursor: pointer;
    margin: 5px;
    width: 70px;
    line-height: 75px;
    font-size: 16;
    transition: all 0.5s;
    
}

#visor{
    width: 240px;
}
<div id='calculadora'>
  <button id='clear' onclick="limpa()">C</button>
  <div id="visor"></div>
  <button class="num" id="n7" value="7" onclick="mostranum(7)">7</button>
  <button class="num" id="n8" value="8" onclick="mostranum(8)">8</button>
  <button class="num" id="n9" value="9" onclick="mostranum(9)">9</button>
  <button class="ops" id="sum" onclick="operator('sum')">+</button>

  <button class="num" id="n4" value="4" onclick="mostranum(4)">4</button>
  <button class="num" id="n5" value="5" onclick="mostranum(5)">5</button>
  <button class="num" id="n6" value="6" onclick="mostranum(6)">6</button>
  <button class="ops" id="subtract" value="-" onclick="operator('subtract')">-</button>

  <button class="num" id="n1" value="1" onclick="mostranum(1)">1</button>
  <button class="num" id="n2" value="2" onclick="mostranum(2)">2</button>
  <button class="num" id="n3" value="3" onclick="mostranum(3)">3</button>
  <button class="ops" id="multiplication" value="*" onclick="operator('multiplication')">*</button>

  <button class="num" id="0" value="0" onclick="mostranum(0)">0</button>
  <button class="ops" id="float" value=".">.</button>
  <button class="result" id="result" onclick="operator('result')">=</button>
  <button class="ops" id="division" value="/" onclick="operator('division')">/</button>

</div>

  • 1

    I edited the question to be able to run code. You can join the CSS to be more visible?

  • it would be simpler to use 2 variables (first and second number= and the operation... even if you wanted to do something like 4+5+6+7+8...etc, tbm would need an array for operation.. could be 4+5/6*7 ... etc this will complicate your code too much, but that’s exactly what you want to do?

  • Exactly Ricardo Pontual, I agree 100%.

  • So Ricardo, I thought: using the buttons the user inserts the value , then the operator , then the second number, but in case he does not choose to finish the operation but to insert a second operator , the operation he put first ex: in a 1 + in a 2 , would be executed and the result stored in the variable that receives the first number and so do the process again

2 answers

2


A version well basic calculator could follow this logic:

  1. keep a number
  2. guard the operation
  3. keep the other number
  4. if typed =, calculate the operation and update the display
  5. the result of the operation becomes first number
  6. back to step 2

In the case of step 4, I could also do the calculation if an operation is entered. I am considering that basic calculator, for example:

  • digit 2: the display shows the number 2
  • digit +: the display does not change (but internally it saved the operation "sum")
  • digit 3: the display shows the number 3
  • digit -: the display shows the result of the previous operation (2 + 3), ie shows 5, and at the same time already stores the operation "subtraction"
  • digit 1: the display shows the number 1
  • digit =: display shows 4 (result of 5 - 1)

And in steps 1 and 3, I also have to update the number. For example, if I type 1 and then 3, the display shall show the number 13.

I also included a limitation: if the number typed passes 9 digits, I do not update. Anyway, an initial version (still incomplete) would look like this:

let tela = document.getElementById('visor');
let n1 = null, n2 = null, operacao = null;
let formatter = Intl.NumberFormat('en', { maximumFractionDigits: 8, useGrouping: false });

function limpa() {
  tela.innerHTML = '';
  n1 = n2 = operacao = null;
}

function atualizaVisor(n) {
   tela.innerHTML = formatter.format(n);
}

function atualizaNumero(atual, novoDigito) { // adiciona um dígito no número atual
    if (atual === null) return novoDigito;

    let novo = atual * 10 + novoDigito;
    if (novo > 999999999) { // só aceito números de até 9 dígitos
        return atual; // retorna o atual, sem modificações
    }

    return novo;
}

function atualizaTela(digito) {
  if (operacao === null) {
    n1 = atualizaNumero(n1, digito);
    atualizaVisor(n1);
  } else {
    n2 = atualizaNumero(n2, digito);
    atualizaVisor(n2);
  }
}

function operator(op) {
  if (operacao !== null) {
     calcula();
  }
  operacao = op;
  if (n2 !== null) {
    calcula();
  }
}

function calcula() {
  let result;
  switch (operacao) {
    case '+':
      result = n1 + n2;
      break;
    case '-':
      result = n1 - n2;
      break;
    case '*':
      result = n1 * n2;
      break;
    case '/':
      result = n1 / n2;
      break;
  }
  atualizaVisor(result);
  n1 = result;
  n2 = operacao = null;
}
body {
    margin: 0;
    background-color: #d44b57;
}

#calculadora {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    width: 130px;
    align-items: center;
    align-content: center;
    margin: auto;
}

button {
    border: 0;
    background: #9d0229;
    color: #ffffff;
    cursor: pointer;
    margin: 5px;
    width: 20px;
    line-height: 25px;
    font-size: 11;
    transition: all 0.5s;
}

#visor{
    width: 83px;
    font-size: 16px;
    text-align: right;
    font-weight: bold;
}
<div id='calculadora'>
  <button id='clear' onclick="limpa()">C</button>
  <div id="visor"></div>
  <button class="num" id="n7" value="7" onclick="atualizaTela(7)">7</button>
  <button class="num" id="n8" value="8" onclick="atualizaTela(8)">8</button>
  <button class="num" id="n9" value="9" onclick="atualizaTela(9)">9</button>
  <button class="ops" id="sum" onclick="operator('+')">+</button>

  <button class="num" id="n4" value="4" onclick="atualizaTela(4)">4</button>
  <button class="num" id="n5" value="5" onclick="atualizaTela(5)">5</button>
  <button class="num" id="n6" value="6" onclick="atualizaTela(6)">6</button>
  <button class="ops" id="subtract" value="-" onclick="operator('-')">-</button>

  <button class="num" id="n1" value="1" onclick="atualizaTela(1)">1</button>
  <button class="num" id="n2" value="2" onclick="atualizaTela(2)">2</button>
  <button class="num" id="n3" value="3" onclick="atualizaTela(3)">3</button>
  <button class="ops" id="multiplication" value="*" onclick="operator('*')">*</button>

  <button class="num" id="0" value="0" onclick="atualizaTela(0)">0</button>
  <button class="ops" id="float" value=".">.</button>
  <button class="result" id="result" onclick="calcula()">=</button>
  <button class="ops" id="division" value="/" onclick="operator('/')">/</button>

</div>

Decreased the size of the buttons to fit the snippet of the site (but as it is only stylization, then you change the way you think best).

I included a decimal formatting (maximum 8 digits after comma) using Intl.NumberFormat (divide 1 by 3, for example, the result would exceed the display limit). Yes it is not quite correct, because if the number is 1000000.123455676, will exceed the display limit (another approach would be to turn the number into string and cut pieces of it, or turn into scientific notation).

Like I said before, is an incomplete version, just to give an idea of where you were going wrong (note that you did not need the array, just save the first and second numbers and the current operation).

Other details are missing, such as:

  • type numbers with decimals (if typed ., has no effect at all for the time being, but simply add the decimal places to the numbers)
  • limit the size of the result (multiply 1 million by 1 million, the result will exceed the limits of the viewfinder)
    • better treat negative numbers and with decimals: the sign of - also occupies a position of the display, as well as the point that separates the decimal places (so do not just see the number of digits, would have to turn into the same string and see the size)
  • etc....

But the basic idea is there.

0

Considerations:

1) At the end of each 'operation', you must 'update' the display element

case 'sum':
        result += num1[c] + num2[c];
        tela.innerHTML = result;
        break;

Otherwise, your 'Memory' (result) will always be wrong. Example.: 8+8 equals 88.

2) I suggest using an input element with Hidden attribute to store the current account result and not an array. This way you always know the value of the last 'operation' because it will be there in the DOM.

<input id='resultado' type='hidden'>
ou
<div id='resultado' style='display: none'></div>
...

let resultado = document.getElementById('resultado');
...

resultado.innerHtml = resultado + num2; // porque num1 é o resultado.
  • I put this code you sent me but it didn’t work, the screen was not showing anything because I am using the console.log for testing, the result is still wrong for some reason, thanks for the suggestions

  • I’m sorry, but I didn’t mean to correct your source code. In fact I guided you to how to solve your problem, because your doubt is very similar to academic papers requested by algorithmic teachers and giving you the answer is not the best way. If it is an academic question, then there is a better way: the mathematical method called "Inverse Polish Notation", which uses the concept of "Stack" (or Array) to perform the operations (and that is what the teacher wants). If it is not academic, then we can eliminate the use of Array, as the hkotsubo friend has already unrolled above.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.