diff --git a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs index b042a5e..43b2786 100644 --- a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs +++ b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs @@ -24,6 +24,7 @@ ce.RegisterFunction("ATANH", 1, Atanh); ce.RegisterFunction("CEILING", 1, Ceiling); ce.RegisterFunction("COMBIN", 2, Combin); + ce.RegisterFunction("COMBINA", 2, CombinA); ce.RegisterFunction("COS", 1, Cos); ce.RegisterFunction("COSH", 1, Cosh); ce.RegisterFunction("COT", 1, Cot); @@ -421,6 +422,24 @@ return XLMath.Combin(n, k); } + private static object CombinA(List p) + { + Int32 number = (int)p[0]; // casting truncates towards 0 as specified + Int32 chosen = (int)p[1]; + + if (number < 0 || number < chosen) + throw new NumberException(); + if (chosen < 0) + throw new NumberException(); + + int n = number + chosen - 1; + int k = number - 1; + + return n == k || k == 0 + ? 1 + : (long)XLMath.Combin(n, k); + } + private static object Degrees(List p) { return p[0] * (180.0 / Math.PI); diff --git a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs index be8bb17..e005e38 100644 --- a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs +++ b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs @@ -1,5 +1,4 @@ using ClosedXML.Excel; -using ClosedXML.Excel.CalcEngine; using ClosedXML.Excel.CalcEngine.Exceptions; using NUnit.Framework; using System; @@ -12,7 +11,42 @@ public class MathTrigTests { private readonly double tolerance = 1e-10; - + + [TestCase(4, 3, 20)] + [TestCase(10, 3, 220)] + [TestCase(0, 0, 1)] + public void Combina_CalculatesCorrectValues(int number, int chosen, int expectedResult) + { + var actualResult = XLWorkbook.EvaluateExpr($"COMBINA({number}, {chosen})"); + Assert.AreEqual(expectedResult, (long)actualResult); + } + + [Theory] + public void Combina_Returns1WhenChosenIs0([Range(0, 10)]int number) + { + Combina_CalculatesCorrectValues(number, 0, 1); + } + + [TestCase(4.23, 3, 20)] + [TestCase(10.4, 3.14, 220)] + [TestCase(0, 0.4, 1)] + public void Combina_TruncatesNumbersCorrectly(double number, double chosen, int expectedResult) + { + var actualResult = XLWorkbook.EvaluateExpr(string.Format( + @"COMBINA({0}, {1})", + number.ToString(CultureInfo.InvariantCulture), + chosen.ToString(CultureInfo.InvariantCulture))); + + Assert.AreEqual(expectedResult, (long)actualResult); + } + + [TestCase(-1, 2)] + [TestCase(0, 0)] + public void Combina_ThrowsNumExceptionOnInvalidValues(int number, int chosen) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr($"COMBINA({number}, {chosen})")); + } + [TestCase(1, 0.642092616)] [TestCase(2, -0.457657554)] [TestCase(3, -7.015252551)]