Power method and exception handling

4

I have to solve the following exercise but I have some doubts:

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

This process should contain an exception if any of the posted numbers are negative.

So far I've made the following code, but I wanted to confirm if it's written as well as possible 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));
    }
}
    
asked by anonymous 15.03.2016 / 18:12

2 answers

5

That's all right, you just have to throw the exception before you run the calculation. Usually when the requirement is to validate the parameters the first thing to do is to use one or more% s of% s with the check and proceed to throw the exception by finishing the execution of the method without doing 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));
    }
}

See working on ideone .

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

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

    
15.03.2016 / 18:23
3

Basic implementation

  

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

It is not clear whether you can use the ready API or whether it should be integer or floating point numbers.

Assuming the answer is not for both cases, one 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 should contain an exception if any of the posted numbers are negative.

Signaling with return value

An approach quoted in comments would be the possibility of returning a special value in case of error.

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

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

For 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 the 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 with 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.

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

One more problem is that it gets all the more confusing because in cases where more than one type of error can occur. Returning false , -1 , queijadinha or xinforímpola does not say much about the problem and you start to depend on error tables.

Exceptions

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

One possibility is to treat negative arguments as illegal using IllegalArgumentException , an approach that is already mentioned in the @bigown 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 constraint you want to enforce, you can also use ArithmeticException , in case it is an invalid math operation. This exception is thrown by Java, for example, when a division by zero occurs. 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 keyword assert that can be used to validate preconditions and cast 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 a check is turned off by default and is more recommended for use in tests than in a real program.

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

java -ea ...

Preconditions

As a reference for more professional use, a preconditions API can be used to assert 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);
}
    
16.03.2016 / 01:54