diff --git a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs index c40485f..f578f42 100644 --- a/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs +++ b/ClosedXML/Excel/CalcEngine/Functions/MathTrig.cs @@ -651,8 +651,19 @@ private static object Fact(List p) { - var num = Math.Floor(p[0]); + var input = p[0].Evaluate(); + + if (!(input is long || input is int || input is byte || input is double || input is float)) + throw new CellValueException(); + + + var num = Math.Floor((double)input); double fact = 1.0; + + + if (num < 0) + throw new NumberException(); + if (num > 1) for (int i = 2; i <= num; i++) fact *= i; diff --git a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs index 5960ddf..72b10fe 100644 --- a/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs +++ b/ClosedXML_Tests/Excel/CalcEngine/MathTrigTests.cs @@ -784,6 +784,44 @@ Assert.AreEqual(expectedResult, actual, tolerance); } + [TestCase(0, 1L)] + [TestCase(1, 1L)] + [TestCase(2, 2L)] + [TestCase(3, 6L)] + [TestCase(4, 24L)] + [TestCase(5, 120L)] + [TestCase(6, 720L)] + [TestCase(7, 5040L)] + [TestCase(8, 40320L)] + [TestCase(9, 362880L)] + [TestCase(10, 3628800L)] + [TestCase(11, 39916800L)] + [TestCase(12, 479001600L)] + [TestCase(13, 6227020800L)] + [TestCase(14, 87178291200L)] + [TestCase(15, 1307674368000L)] + [TestCase(16, 20922789888000L)] + [TestCase(0.1, 1L)] + [TestCase(2.3, 2L)] + [TestCase(2.8, 2L)] + public void Fact_ReturnsCorrectResult(double input, long expectedResult) + { + var actual = (double)XLWorkbook.EvaluateExpr(string.Format(@"FACT({0})", input.ToString(CultureInfo.InvariantCulture))); + Assert.AreEqual(expectedResult, actual); + } + + [Theory] + public void Fact_ThrowsNumberExceptionForNegativeInput([Range(-10, -1)] int input) + { + Assert.Throws(() => XLWorkbook.EvaluateExpr(string.Format(@"FACT({0})", input.ToString(CultureInfo.InvariantCulture)))); + } + + [Test] + public void Fact_ThrowsValueExceptionForNonNumericInput() + { + Assert.Throws(() => XLWorkbook.EvaluateExpr(string.Format(@"FACT(""x"")"))); + } + [Test] public void Floor() {