diff --git a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs index 36cfadd..c40485f 100644 --- a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs +++ b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs @@ -601,8 +601,28 @@ private static object Combin(List p) { - Int32 n = (int)p[0]; - Int32 k = (int)p[1]; + Int32 n; + Int32 k; + + var rawN = p[0].Evaluate(); + var rawK = p[1].Evaluate(); + if (rawN is long || rawN is int || rawN is byte || rawN is double || rawN is float) + n = (int)Math.Floor((double)rawN); + else + throw new NumberException(); + + if (rawK is long || rawK is int || rawK is byte || rawK is double || rawK is float) + k = (int)Math.Floor((double)rawK); + else + throw new NumberException(); + + + n = (int)p[0]; + k = (int)p[1]; + + if (n < 0 || n < k || k < 0) + throw new NumberException(); + return XLMath.Combin(n, k); } diff --git a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs index a609646..ff7a186 100644 --- a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs +++ b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs @@ -447,6 +447,72 @@ Assert.AreEqual(expectedResult, actual); } + [Theory] + public void Combin_ThrowsNumberExceptionForAnyArgumentSmaller0([Range(-4, -1)] int smaller0) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr( + string.Format( + @"COMBIN({0}, {1})", + smaller0.ToString(CultureInfo.InvariantCulture), + (-smaller0).ToString(CultureInfo.InvariantCulture)))); + + Assert.Throws(() => XLWorkbook.EvaluateExpr( + string.Format( + @"COMBIN({0}, {1})", + (-smaller0).ToString(CultureInfo.InvariantCulture), + smaller0.ToString(CultureInfo.InvariantCulture)))); + } + + [TestCase("\"no number\"")] + [TestCase("\"\"")] + public void Combin_ThrowsNumericExceptionForAnyArgumentNotNumeric(string input) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr( + string.Format( + @"COMBIN({0}, 1)", + input?.ToString(CultureInfo.InvariantCulture)))); + + Assert.Throws(() => XLWorkbook.EvaluateExpr( + string.Format( + @"COMBIN(1, {0})", + input?.ToString(CultureInfo.InvariantCulture)))); + } + + [Theory] + public void Combin_Returns1ForKis0OrKEqualsN([Range(0, 10)] int n) + { + var actual = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, 0)", n)); + Assert.AreEqual(1, actual); + + var actual2 = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, {0})", n)); + Assert.AreEqual(1, actual2); + } + + [Theory] + public void Combin_ReturnsNforKis1OrKisNminus1([Range(1, 10)] int n) + { + var actual = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, 1)", n)); + Assert.AreEqual(n, actual); + + var actual2 = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, {1})", n, n-1)); + Assert.AreEqual(n, actual2); + } + + [TestCase(4, 2, 6)] + [TestCase(5, 2, 10)] + [TestCase(6, 2, 15)] + [TestCase(6, 3, 20)] + [TestCase(7, 2, 21)] + [TestCase(7, 3, 35)] + public void Combin_ReturnsCorrectResults(int n, int k, int expectedResult) + { + var actual = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, {1})", n, k)); + Assert.AreEqual(expectedResult, actual); + + var actual2 = XLWorkbook.EvaluateExpr(string.Format(@"COMBIN({0}, {1})", n, n-k)); + Assert.AreEqual(expectedResult, actual2); + } + [TestCase(4, 3, 20)] [TestCase(10, 3, 220)] [TestCase(0, 0, 1)]