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);
}
if(a < 0 || b < 0) throw new IllegalArgumentException("Alguma mensagem...");
?– Renan Gomes