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);
}