@Test public void testBinomialCoefficient() { long[] bcoef5 = {1, 5, 10, 10, 5, 1}; long[] bcoef6 = {1, 6, 15, 20, 15, 6, 1}; for (int i = 0; i < 6; i++) { Assert.assertEquals("5 choose " + i, bcoef5[i], ArithmeticUtils.binomialCoefficient(5, i)); } for (int i = 0; i < 7; i++) { Assert.assertEquals("6 choose " + i, bcoef6[i], ArithmeticUtils.binomialCoefficient(6, i)); } for (int n = 1; n < 10; n++) { for (int k = 0; k <= n; k++) { Assert.assertEquals( n + " choose " + k, binomialCoefficient(n, k), ArithmeticUtils.binomialCoefficient(n, k)); Assert.assertEquals( n + " choose " + k, binomialCoefficient(n, k), ArithmeticUtils.binomialCoefficientDouble(n, k), Double.MIN_VALUE); Assert.assertEquals( n + " choose " + k, FastMath.log(binomialCoefficient(n, k)), ArithmeticUtils.binomialCoefficientLog(n, k), 10E-12); } } int[] n = {34, 66, 100, 1500, 1500}; int[] k = {17, 33, 10, 1500 - 4, 4}; for (int i = 0; i < n.length; i++) { long expected = binomialCoefficient(n[i], k[i]); Assert.assertEquals( n[i] + " choose " + k[i], expected, ArithmeticUtils.binomialCoefficient(n[i], k[i])); Assert.assertEquals( n[i] + " choose " + k[i], expected, ArithmeticUtils.binomialCoefficientDouble(n[i], k[i]), 0.0); Assert.assertEquals( "log(" + n[i] + " choose " + k[i] + ")", FastMath.log(expected), ArithmeticUtils.binomialCoefficientLog(n[i], k[i]), 0.0); } }
@Test public void testFactorial() { for (int i = 1; i < 21; i++) { Assert.assertEquals(i + "! ", factorial(i), ArithmeticUtils.factorial(i)); Assert.assertEquals( i + "! ", factorial(i), ArithmeticUtils.factorialDouble(i), Double.MIN_VALUE); Assert.assertEquals( i + "! ", FastMath.log(factorial(i)), ArithmeticUtils.factorialLog(i), 10E-12); } Assert.assertEquals("0", 1, ArithmeticUtils.factorial(0)); Assert.assertEquals("0", 1.0d, ArithmeticUtils.factorialDouble(0), 1E-14); Assert.assertEquals("0", 0.0d, ArithmeticUtils.factorialLog(0), 1E-14); }
/** Tests correctness for large n and sharpness of upper bound in API doc JIRA: MATH-241 */ @Test public void testBinomialCoefficientLarge() throws Exception { // This tests all legal and illegal values for n <= 200. for (int n = 0; n <= 200; n++) { for (int k = 0; k <= n; k++) { long ourResult = -1; long exactResult = -1; boolean shouldThrow = false; boolean didThrow = false; try { ourResult = ArithmeticUtils.binomialCoefficient(n, k); } catch (MathArithmeticException ex) { didThrow = true; } try { exactResult = binomialCoefficient(n, k); } catch (MathArithmeticException ex) { shouldThrow = true; } Assert.assertEquals(n + " choose " + k, exactResult, ourResult); Assert.assertEquals(n + " choose " + k, shouldThrow, didThrow); Assert.assertTrue(n + " choose " + k, (n > 66 || !didThrow)); if (!shouldThrow && exactResult > 1) { Assert.assertEquals( n + " choose " + k, 1., ArithmeticUtils.binomialCoefficientDouble(n, k) / exactResult, 1e-10); Assert.assertEquals( n + " choose " + k, 1, ArithmeticUtils.binomialCoefficientLog(n, k) / FastMath.log(exactResult), 1e-10); } } } long ourResult = ArithmeticUtils.binomialCoefficient(300, 3); long exactResult = binomialCoefficient(300, 3); Assert.assertEquals(exactResult, ourResult); ourResult = ArithmeticUtils.binomialCoefficient(700, 697); exactResult = binomialCoefficient(700, 697); Assert.assertEquals(exactResult, ourResult); // This one should throw try { ArithmeticUtils.binomialCoefficient(700, 300); Assert.fail("Expecting MathArithmeticException"); } catch (MathArithmeticException ex) { // Expected } int n = 10000; ourResult = ArithmeticUtils.binomialCoefficient(n, 3); exactResult = binomialCoefficient(n, 3); Assert.assertEquals(exactResult, ourResult); Assert.assertEquals(1, ArithmeticUtils.binomialCoefficientDouble(n, 3) / exactResult, 1e-10); Assert.assertEquals( 1, ArithmeticUtils.binomialCoefficientLog(n, 3) / FastMath.log(exactResult), 1e-10); }