MATH-1047
Overflow checking in "ArithmeticUtils.pow(int,int)". Added "LocalizedFormats.BASE" error pattern. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1536683 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
27bbf640fe
commit
53f55d2ca0
|
@ -205,6 +205,7 @@ public enum LocalizedFormats implements Localizable {
|
||||||
NOT_POSITIVE_ELEMENT_AT_INDEX("element {0} is not positive: {1}"),
|
NOT_POSITIVE_ELEMENT_AT_INDEX("element {0} is not positive: {1}"),
|
||||||
NOT_POSITIVE_EXPONENT("invalid exponent {0} (must be positive)"),
|
NOT_POSITIVE_EXPONENT("invalid exponent {0} (must be positive)"),
|
||||||
NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE("number of elements should be positive ({0})"),
|
NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE("number of elements should be positive ({0})"),
|
||||||
|
BASE("base ({0})"), /* keep */
|
||||||
EXPONENT("exponent ({0})"), /* keep */
|
EXPONENT("exponent ({0})"), /* keep */
|
||||||
NOT_POSITIVE_LENGTH("length must be positive ({0})"),
|
NOT_POSITIVE_LENGTH("length must be positive ({0})"),
|
||||||
LENGTH("length ({0})"), /* keep */
|
LENGTH("length ({0})"), /* keep */
|
||||||
|
|
|
@ -632,25 +632,45 @@ public final class ArithmeticUtils {
|
||||||
*
|
*
|
||||||
* @param k Number to raise.
|
* @param k Number to raise.
|
||||||
* @param e Exponent (must be positive or zero).
|
* @param e Exponent (must be positive or zero).
|
||||||
* @return k<sup>e</sup>
|
* @return \( k^e \)
|
||||||
* @throws NotPositiveException if {@code e < 0}.
|
* @throws NotPositiveException if {@code e < 0}.
|
||||||
|
* @throws MathArithmeticException if the result would overflow.
|
||||||
*/
|
*/
|
||||||
public static int pow(final int k, int e) throws NotPositiveException {
|
public static int pow(final int k,
|
||||||
|
final int e)
|
||||||
|
throws NotPositiveException,
|
||||||
|
MathArithmeticException {
|
||||||
if (e < 0) {
|
if (e < 0) {
|
||||||
throw new NotPositiveException(LocalizedFormats.EXPONENT, e);
|
throw new NotPositiveException(LocalizedFormats.EXPONENT, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = 1;
|
try {
|
||||||
int k2p = k;
|
int exp = e;
|
||||||
while (e != 0) {
|
int result = 1;
|
||||||
if ((e & 0x1) != 0) {
|
int k2p = k;
|
||||||
result *= k2p;
|
while (true) {
|
||||||
}
|
if ((exp & 0x1) != 0) {
|
||||||
k2p *= k2p;
|
result = mulAndCheck(result, k2p);
|
||||||
e = e >> 1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
exp >>= 1;
|
||||||
|
if (exp == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
k2p = mulAndCheck(k2p, k2p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (MathArithmeticException mae) {
|
||||||
|
// Add context information.
|
||||||
|
mae.getContext().addMessage(LocalizedFormats.OVERFLOW);
|
||||||
|
mae.getContext().addMessage(LocalizedFormats.BASE, k);
|
||||||
|
mae.getContext().addMessage(LocalizedFormats.EXPONENT, e);
|
||||||
|
|
||||||
|
// Rethrow.
|
||||||
|
throw mae;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -176,6 +176,7 @@ DEGREES_OF_FREEDOM = degr\u00e9s de libert\u00e9 ({0})
|
||||||
NOT_POSITIVE_ELEMENT_AT_INDEX = l''\u00e9l\u00e9ment {0} n''est pas positif : {1}
|
NOT_POSITIVE_ELEMENT_AT_INDEX = l''\u00e9l\u00e9ment {0} n''est pas positif : {1}
|
||||||
NOT_POSITIVE_EXPONENT = exposant {0} invalide (doit \u00eatre positif)
|
NOT_POSITIVE_EXPONENT = exposant {0} invalide (doit \u00eatre positif)
|
||||||
NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE = le nombre d''\u00e9l\u00e9ments devrait \u00eatre positif ({0})
|
NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE = le nombre d''\u00e9l\u00e9ments devrait \u00eatre positif ({0})
|
||||||
|
BASE = base ({0})
|
||||||
EXPONENT = exposant ({0})
|
EXPONENT = exposant ({0})
|
||||||
NOT_POSITIVE_LENGTH = la longueur doit \u00eatre positive ({0})
|
NOT_POSITIVE_LENGTH = la longueur doit \u00eatre positive ({0})
|
||||||
LENGTH = longueur ({0})
|
LENGTH = longueur ({0})
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class LocalizedFormatsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessageNumber() {
|
public void testMessageNumber() {
|
||||||
Assert.assertEquals(314, LocalizedFormats.values().length);
|
Assert.assertEquals(315, LocalizedFormats.values().length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -460,6 +460,50 @@ public class ArithmeticUtilsTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected=MathArithmeticException.class)
|
||||||
|
public void testPowIntIntOverflow() {
|
||||||
|
final int base = 21;
|
||||||
|
final int exp = 8;
|
||||||
|
ArithmeticUtils.pow(base, exp);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testPowIntIntNoOverflow() {
|
||||||
|
final int base = 21;
|
||||||
|
final int exp = 7;
|
||||||
|
ArithmeticUtils.pow(base, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=MathArithmeticException.class)
|
||||||
|
public void testPowNegativeIntIntOverflow() {
|
||||||
|
final int base = -21;
|
||||||
|
final int exp = 8;
|
||||||
|
ArithmeticUtils.pow(base, exp);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testPowNegativeIntIntNoOverflow() {
|
||||||
|
final int base = -21;
|
||||||
|
final int exp = 7;
|
||||||
|
ArithmeticUtils.pow(base, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPowMinusOneInt() {
|
||||||
|
final int base = -1;
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final int pow = ArithmeticUtils.pow(base, i);
|
||||||
|
Assert.assertEquals("i: " + i, i % 2 == 0 ? 1 : -1, pow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPowOneInt() {
|
||||||
|
final int base = 1;
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
final int pow = ArithmeticUtils.pow(base, i);
|
||||||
|
Assert.assertEquals("i: " + i, 1, pow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsPowerOfTwo() {
|
public void testIsPowerOfTwo() {
|
||||||
final int n = 1025;
|
final int n = 1025;
|
||||||
|
|
Loading…
Reference in New Issue