Power Calculator in Javascript

Asked

Viewed 2,803 times

1

I’m trying to perform a power calculator, but always returns the result with 0 and I don’t know where the logic error is. I’ve redone the code a few times with more or less lines.

var numero, potencia;
var resultado = 0;


function ColetarInformacoes(){

    numero = prompt("Qual número será elevado ?");
    numero = parseInt(numero);

    potencia = prompt(" Elevado á qual potência ? ");
    potencia = parseInt(potencia);

    ValidarInformacoes();

}

function ValidarInformacoes(){

    if(numero  !== undefined || potencia !== undefined){
        throw new Error("Não aceitamos valores undefined...");
    }

    if(numero < 0){
        throw new Error("Calcula somente números positivos..."); 
    }

    if(isNaN(numero) || isNaN(potencia)){
        throw new Error("Os valores inseridos não são válidos...");
    }

}

function Calcular(){

    ColetarInformacoes();

    for(var i = 0; i < potencia; i++){
        resultado *= numero;
     }

    alert("O resultado é "+ resultado);
}
  • Your code has logic errors. if(number === Undefined || power === Undefined)

  • You must change this part to put to check if it is fully Undefined

2 answers

9


I’m assuming it’s an exercise (or a code for training), since to calculate power, it’s best to use Math.pow, as suggested in the other answer (inclusive, it treats other cases that your code does not, but we will see this in detail below).


The problem is that its variable resultado starts with the value zero. Then when you arrive at this loop:

for (var i = 0; i < potencia; i++){
    resultado *= numero;
}

You will be multiplying the number by zero several times, and the result will be zero (a tip is to do the table test, that errors like that are discovered quickly).

To fix it is simple, just boot resultado with 1 (which is the neutral element of multiplication).

Another detail is that in the validation you were doing:

if(numero !== undefined || potencia !== undefined){
    throw new Error("Não aceitamos valores undefined...");
}

That is, if numero nay for undefined, or if potencia nay for undefined, gives error. But the right would be to check if they are undefined, using === instead of !==.

But actually you don’t need this if, as it has previously been used parseInt to transform the typed text into number, so the variables will not be undefined. If the person does not enter a valid number, parseInt returns NaN, then just check this (incidentally, it is better to check if it is NaN before to see if the value is zero, because it makes no sense to test if the value is less than zero if it is NaN).

You could also avoid global variables and make the function that reads the data return the read numbers.

The code would look like this:

function lerDados(){
    let numero = parseInt(prompt("Qual número será elevado?"));
    let potencia = parseInt(prompt("Elevado a qual potência?"));

    return validar(numero, potencia);
}

function validar(numero, potencia){
    // verifica antes se é NaN (não faz sentido testar se é < 0 antes de saber se é NaN)
    if (isNaN(numero) || isNaN(potencia)){
        throw new Error("Os valores inseridos não são válidos...");
    }

    if (numero < 0 || potencia < 0){
        throw new Error("Calcula somente números positivos..."); 
    }

    // retorna um array com os valores
    return [numero, potencia];
}

function calcular(){
    // obter os valores usando a sintaxe de destructuring assignment
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
    let [numero, potencia] = lerDados();
    let resultado = 1;

    for (let i = 0; i < potencia; i++){
        resultado *= numero;
    }

    alert("O resultado é "+ resultado);
}

calcular();


Note also that I used let instead of var to declare variables. To know the difference, see this question.

I also put in the checks if the power is negative (since you are not calculating this). But if you want negative exponents, just change the calculation to:

if (potencia < 0) {
    potencia *= -1;
    numero = 1 / numero;
}
for (let i = 0; i < potencia; i++){
    resultado *= numero;
}

Finally, I did not include a special check when the basis and exponent are zero (since zero to zero is undefined). But if you want, you can include:

if (numero === 0 && potencia === 0) {
    throw new Error("Zero elevado a zero é indefinido"); 
}

About the string to number conversion

The other answer said (before it is edited) to use + instead of parseInt to convert typed text to number. Although the result is the same for integers, there are cases where there may be a difference).

For example, if the person type 2.5, the conversion with parseInt results in 2, as long as + results in 2.5:

let texto = "2.5";

console.log(parseInt(texto)); // 2
console.log(+texto); // 2.5

To the groundwork, there is no problem having a number with several decimal places, but in your case as you are making a loop simple and multiplying a certain amount of times, your code does not serve to exponents decimal.

I mean, your code would handle 2.5 raised to 3 (because 2.5 would be multiplied 3 times), but not with 3 raised to 2.5, for parseInt will round the power to 2.

But the worst is if you convert with +, because in that case the for would multiply 3 times:

let numero = +"3";
let potencia = +"2.5";

let resultado = 1;
for (let i = 0; i < potencia; i++){
    resultado *= numero;
}
console.log(resultado); // 27

Like the + converts the string to 2.5, the for iterates 3 times (since in the third iteration, it compares i < potencia, and how i vale 2 and potencia vale 2.5, it iterates more than it should). That’s why the result is 27.

Therefore, to the groundwork, there is no problem in having decimal places, and you can use parseFloat, which reads both whole numbers and decimal places. Already exponent, better keep parseInt even, since your code only handles entire exponents:

let numero = parseFloat(prompt("Qual número será elevado?"));
let potencia = parseInt(prompt("Elevado a qual potência?"));

Of course you can use + instead of parseFloat to read the basis, but I still prefer to use the functions, whose names make it very clear what is happening. A clearer, more expressive code is better than a shorter code (and in that case it’s not even that short).

If you want to consider exponents as 2.5, then you better use Math.pow even, who already knows how to deal with all these cases.

There is another case, which is when the user only gives one ENTER in the prompt. In this case, the string will be empty, and use + gives different results from parseInt and parseFloat:

let texto = "";

console.log(parseInt(texto)); // NaN
console.log(parseFloat(texto)); // NaN
console.log(+texto); // 0

parseInt and parseFloat return NaN, that is, if the user enters an empty string, the validation code will say that the entries are invalid. But use + returns zero, so at the end it considers that an empty string is a valid input.

Same goes for when the string only has spaces (" "). So using one or the other makes a difference yes, especially in these corner cases, that you have to decide whether to consider valid or not. If you ask the user to enter something, the code has to be prepared to validate this thing, and only proceed if the data is valid.

Anyway, don’t trade one method for another just because it’s "shorter" or because it looks "cooler". Learn the implications of each and use what makes the most sense for what you intend to do.

3

Solution:

  1. Use the method Math.pow for power calculations.
  2. When you compared if it is undefined, you used !== which is the type and value negation operator, switch to ==.
  3. The comparison if it is Undefined is useless, because when changing to number is not in Undefined, but as Nan
  4. Place the prompt inside the parseint function, because it is unnecessary to receive a number from the prompt and then in another line change the type of the value to number.
  5. Leave these "number, power and result" variables inside the function and use Let(scope variable) to declare the data type.
  6. If none of the checks give true, it returns a value(use if,Else if, Else).

Calcular();


function ColetarInformacoes() {

  let numero = parseInt(prompt("Qual número será elevado ?"));

  let potencia = parseInt(prompt(" Elevado á qual potência ? "));

  return ValidarInformacoes(numero, potencia);
}

function ValidarInformacoes(numero, potencia) {

  if (numero < 0) {
    throw new Error("Calcula somente números positivos...");
  } else if (isNaN(numero) || isNaN(potencia)) {
    throw new Error("Os valores inseridos não são válidos...");
  } else {
    return [numero, potencia];
  }

}

function Calcular() {

  let [numero, potencia] = ColetarInformacoes();
  let resultado = Math.pow(numero, potencia)
  console.log("Valor é: " + resultado)
}

  • 1

    There are cases where the + gives different results from parseInt, then I would not give the suggestion to exchange without justification and without understanding all the implications. In the my answer I show cases where gives difference :-)

  • 4

    If you know the difference, you could have explained it in your answer. If you just say change, without explaining the reason, one can understand that the other way is wrong (but it’s not, it just works differently in some cases). The idea of Stack Overflow is that the answers are useful not only to those who asked, but to anyone who visits the site in the future, so it is important to explain these things. I hope you understand and do not take my comment wrong, it was a constructive criticism, so that your response (and the site as a whole) improve.

  • 2

    In item 2, besides containing no explanation, it assumes that the AP wants to calculate the accepting power float as a basis and implies that it is the right way to be done, when it is just different. That, and your stance with the colleague who tried to help you improve your answer, are the justifications of my downvote. You’re welcome!

  • Editing solved the previous problem, downvote removed.

Browser other questions tagged

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