diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index e3f02e093..d17ff0df7 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -608,6 +608,18 @@ It is the forward difference with a step of 1, as Mathematica's `DifferenceDelta
| `"forwarddifference(k^2, k)".ToEntity().Simplify()` | throws `UnhandledParseException` | `1 + 2 * k` |
| `"forwarddifference(2^k, k)".ToEntity()` | throws `UnhandledParseException` | `2 ^ (k + 1) - 2 ^ k` |
+### A binomial with a whole upper argument and a lower one that is not whole is evaluated
+
+**Not silent: what threw is a number.** `binomial(n, k)` with a whole `n` and a `k` that is not whole was left as
+written, so `EvalNumerical` threw `CannotEvalException`. It is the gamma ratio `Γ(n + 1)/(Γ(k + 1) Γ(n - k + 1))`, as
+for any other `n`, and for a negative whole `n` it has no value: `Γ(n + 1)` has a pole there
+([#1411](https://github.com/asc-community/AngouriMath/issues/1411)).
+
+| Input | Was (2.6.0) | Now |
+|---|---|---|
+| `"binomial(3, 1/2)".ToEntity().EvalNumerical()` | `CannotEvalException` | `2.0371832715762602978…`, `32/(5 pi)` |
+| `"binomial(-3, 1/2)".ToEntity().EvalNumerical()` | `CannotEvalException` | `NaN` |
+
### The harmonic numbers
**Not silent: `harmonicnumber(n)` and `harmonicnumber(n, m)` are the harmonic numbers, where the one was a product and the
diff --git a/Sources/AngouriMath/Functions/Evaluation/Evaluation.Continuous/Evaluation.Continuous.Arithmetics.Classes.cs b/Sources/AngouriMath/Functions/Evaluation/Evaluation.Continuous/Evaluation.Continuous.Arithmetics.Classes.cs
index c2f8e8f43..6f2a617db 100644
--- a/Sources/AngouriMath/Functions/Evaluation/Evaluation.Continuous/Evaluation.Continuous.Arithmetics.Classes.cs
+++ b/Sources/AngouriMath/Functions/Evaluation/Evaluation.Continuous/Evaluation.Continuous.Arithmetics.Classes.cs
@@ -566,9 +566,12 @@ protected override Entity InnerSimplify(bool isExact) =>
// negative n included: binomial(-1, 3) = (-1)(-2)(-3)/3! = -1.
(Number top, Integer bottom) when bottom.EInteger.CanFitInInt32() => FallingFactorialOver(top, bottom.EInteger.ToInt32Unchecked()),
(_, Integer { IsZero: true }) => Integer.Create(1),
- // Through the gamma function only numerically: there is no exact form.
+ // A k that is not whole has no value with a negative whole n, a pole of Γ(n + 1).
+ (Integer { EInteger.Sign: < 0 }, Complex bottom) when bottom is not Integer => MathS.NaN,
+ // Through the gamma function only numerically: there is no exact form. A whole n
+ // takes it too: binomial(3, 1/2) is 32/(5 pi).
(Complex top, Complex bottom) when !isExact
- && top is not Integer && Number.Factorial(top) is var topF && Number.Factorial(bottom) is var bottomF
+ && Number.Factorial(top) is var topF && Number.Factorial(bottom) is var bottomF
&& Number.Factorial(top - bottom) is var restF && !topF.IsNaN && !bottomF.IsNaN && !restF.IsNaN
=> topF / (bottomF * restF),
_ => null
diff --git a/Sources/Tests/UnitTests/Convenience/BinomialTest.cs b/Sources/Tests/UnitTests/Convenience/BinomialTest.cs
index 6a01ed231..1269ac20f 100644
--- a/Sources/Tests/UnitTests/Convenience/BinomialTest.cs
+++ b/Sources/Tests/UnitTests/Convenience/BinomialTest.cs
@@ -67,6 +67,26 @@ public void AFractionalLowerArgumentEvaluatesThroughTheGammaFunction()
Assert.True(Math.Abs((double)value.RealPart - 2.5) < 1e-9, $"binomial(5/2, 3/2) evaluated to {value}");
}
+ ///
+ /// A whole upper argument with a lower one that is not whole goes through the gamma function
+ /// as well, against mpmath to 25 digits: binomial(3, 1/2) is 32/(5 pi). It was
+ /// left unevaluated. With a negative whole upper argument there is no value.
+ ///
+ [Theory]
+ [InlineData("binomial(3, 1/2)", "2.03718327157626029784171217117")]
+ [InlineData("binomial(0, 1/2)", "0.63661977236758134307553505349")]
+ [InlineData("binomial(4, 3/2)", "5.43248872420336079424456578978")]
+ [InlineData("binomial(3, -1/2)", "0.291026181653751471120244595881")]
+ public void AWholeUpperArgumentWithAFractionalLowerOneEvaluatesThroughTheGammaFunction(string input, string expected)
+ {
+ var value = Assert.IsAssignableFrom(input.ToEntity().EvalNumerical());
+ Assert.True(value.EDecimal.Subtract(PeterO.Numbers.EDecimal.FromString(expected)).Abs().CompareTo(PeterO.Numbers.EDecimal.FromString("1e-25")) < 0, $"{input} evaluated to {value}");
+ }
+
+ [Fact]
+ public void ANegativeWholeUpperArgumentWithAFractionalLowerOneHasNoValue()
+ => Assert.Equal(MathS.NaN, "binomial(-3, 1/2)".ToEntity().EvalNumerical());
+
///
/// Every whole k has a value, whatever n is; a k that is not whole has one unless n is
/// a negative whole number, where Γ(n + 1) has a pole.