Power method and exception treatment

Asked

Viewed 232 times

4

I must resolve the following exercise but I have some doubts:

Create a class with only one method power, which receives 2 numbers and calculates the number 1 to the number 2.

This process must contain an exception if any of the numbers released are negative.

So far I have made the following code, but I wanted to confirm if it is written in the best possible way and how should I make the exception.

public class Calculadora
{
    public static int power(int n, int p) {
        return (int)Math.pow(n, p);
    }

    public static void main(String[] args) {
        System.out.println(power(10,2));
    }
}
  • 3

    if(a < 0 || b < 0) throw new IllegalArgumentException("Alguma mensagem...");?

2 answers

5


It’s all right, just throw the exception before you run the calculation. Usually when the requirement is to validate the parameters the first thing you do is to use one or more ifs with the verification and proceeds to launch the exception ending the execution of the method without executing anything else.

import java.lang.*;

class Calculadora {
    public static int power(int n, int p) {
        if (n < 0 || p < 0) throw new IllegalArgumentException("n ou p"); //poderia sofisticar a mensagem.
        return (int)Math.pow(n, p);
    }
    public static void main(String[] args) {
        System.out.println(power(10, 2));
    }
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Eventually some method may be more interesting to go out by mistake otherwise, but it is not case, not only by the requirement of the question, but also because otherwise it could be ambiguous or would require a change of type and unnecessary complication to the case. Not the Java way to do it.

There are other possible techniques, but this is appropriate to the question.

  • 1

    Have you surrendered to making exceptions? : p I would return -1 when the value is invalid, so as not to cast exception, following your recommendation of another question.

  • It worked, I just don’t understand why I add the throw before passing the vestments (10 and 2) in this case.

  • @Rafaelaugusto if the values do not meet the condition of the if, the exception for the flow of the method, launching to the one who called it (in case the main), so it was not necessary.

  • @Rafaelaugusto Because first you check if the established conditions were met, if they were not, the method should terminate the execution immediately and do nothing else.

  • @bigown In case it starts reading the Main method(where are the values of N and P) then goes through the if of the power method. That would be it ?

  • 1

    @Diegof this is a case to use exception. Although I prefer contracts (which Java does not have) that will only throw an exception in the latter case. Note that this is a programming error exception that should never be captured. Deep down I would rather have a different exception mechanism to indicate the fail-fast that this should provoke. Nor should give the chance to capture. Obviously the return of -1 can make sense depending on the definition of what you want.

  • @Rafaelaugusto I could say that I think this is it, but I may have got it wrong, it’s kind of weird

  • @Diegof -1 is a bad idea: power(-1, 3)

  • @utluiz I would first treat the values as the bigown did, and if they were invalid, return -1 to the method that called it, already the Math.power, would put in a else, I wouldn’t pass the -1 to him not kk

  • @Diegof I don’t think you understand. The return of power(-1, 3) is -1. Therefore, a return -1 is perfectly valid for routine.

  • @Diegof what he meant is that in this case the -1 might be a valid value, so you would be using an ambiguous error code.

  • Oh yes, I mistook power for what makes square root kkkk my mistake.

  • 1

    @Diegof handling errors is very difficult, with everything I wrote I know that most people will make mistakes on how to do this, I live making mistakes, language developers and frameworks They’ve made a lot of those mistakes and they still do. Of course I answered something simplified, if I were to make a code that went beyond an exercise, I would do better than that, but still it would be with an exception. In Java I see no better way to treat this situation in this case.

Show 8 more comments

3

Basic implementation

Create a class that has only one power method, which takes 2 numbers and calculates the number 1 to the number 2.

It is unclear whether you can use ready-made API or whether it should be integer or floating-point numbers.

Assuming the answer is no for both cases, a solution would be:

int power(int n, int p) {
    int r = 1;
    for (int i = 0; i < p; i++) {
        r *= n;
    }
    return r;
}

Another functional form (Java 8) would be:

int power(int n, int p) {
    return IntStream.range(0, p).reduce(1, (a, b) -> a * n);
}

If, however, you need to do this for floating point values, do so:

double power(double n, double p) {
    return Math.pow(n, p);
}

Validation

This process must contain an exception if any of the numbers released are negative.

Signaling with return value

An approach cited in comments would be the possibility to return a special value in case of error.

This type of approach is very tempting at first, when modelling some library or API.

This is widely used weak typing languages like PHP or others that have no exceptions.

In the case of PHP, for example, a function can return a number, a boolean, or any other value dynamically. See the example:

$pos = strrpos($mystring, "b");
if ($pos === false) { ... }

The return of strrpos is the position of "b" in string or false if not found. This makes it necessary to test the return with === otherwise $pos == false or !$pos would evaluate to true if $pos was zero, which leads to frequent bugs in programs.

Another problem of using a "special value" to denote errors is to assume that each routine has a range of values that is never used. This is not always possible.

Yet another problem is that it is very difficult to create any pattern to denote the error, since each routine has its own valid return types.

Another problem is that everything gets more confused because in cases where more than one type of error may occur. Return false, -1, queijadinha or xinforímpola doesn’t say much about the problem and you get to depend on error tables.

Exceptions

Although slower, the exceptions provide a clearer way to denote problems.

One possibility is to treat negative arguments as illegal using IllegalArgumentException, approach already cited in the @Maniero response:

int power(int n, int p) {
    if (n < 0 || p < 0) {
        throw new IllegalArgumentException("Argumento negativo!");
    }
    return (int) Math.pow(n, p);
}

Depending on the type of restriction you want to impose, you can also use ArithmeticException, in the case of an invalid mathematical operation. This exception is thrown by Java, for example, when a division occurs by zero. It would look like this:

int power(int n, int p) {
    if (n < 0 || p < 0) {
        throw new ArithmeticException("Argumento negativo!");
    }
    return (int) Math.pow(n, p);
}

Assertions

Java has the reserved word assert which can be used to validate preconditions and launch a AssertionError if the condition is not met.

Example:

int power(int n, int p) {
    assert n >= 0 && p >= 0;
    return (int) Math.pow(n, p);
}

The disadvantage of assert is that such verification is turned off by default and is more recommended for use in tests than in a truth program.

However, you can activate assertions for the entire program or selectively in some classes. The simplest way is to pass the parameter -ea to Java like this:

java -ea ...

Preconditions

As a reference for more professional use, a precondition API can be used to assert the parameters. There are different implementations like Valid4j or Google Guava.

In Valid4j an example would be:

int power(int n, int p) {
    require(n, greaterThanOrEqualTo(0));
    require(p, greaterThanOrEqualTo(0));
    return (int) Math.pow(n, p);
}

In Guava:

int power(int n, int p) {
    checkArgument(n >= 0, "Esperado n positivo, mas n = %s", n);
    checkArgument(p >= 0, "Esperado p positivo, mas p = %s", p);
    return (int) Math.pow(n, p);
}

Browser other questions tagged

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