# Expression evaluates to a different number when made a function

The following expression evaluates to zero at large n when just using replacement, but if the same expression is defined as a function f[n], it suddenly evaluates to a nonzero number. Redefining the function by absorbing the denominator into Hypergeometric2F1Regularized again gives a vanishing answer. Applying N to all of these gives a nonzero answer. Is this an issue with precision control, and if so, how do I fix it, and which result should I trust?

exp = n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n, 2 + n, -1]
f[n_] := n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n, 2 + n, -1]
f1[n_] := n^2/2 Gamma[n + 1/2] Hypergeometric2F1Regularized[1, 1 - n, 2 + n, -1]
f1[n] == f[n] // FullSimplify
{exp /. {n -> 256.}, f[256.], f1[256.], N[exp /. {n -> 256}], N[f[256]], N[f1[256]]}


Output: {0., 109.439, 0., 109.439, 109.439, 109.439}.

• It should be mentioned that your code produces a warning about potential loss of precision (at least for me). Also, f[n]/.n->256. gives the same result as using exp, so I guess it's an issue with the expression being rewritten when n is used instead of a number. Lastly, why not simply use f[256] or N[f[256]]? - this way, you don't have any issues with machine precision numbers Sep 13, 2020 at 17:10
• @LukasLang yeah I guess I’m trying to understand the difference between all of these things. N[f[n]] seems to be extremely slow, but maybe that’s just a sign of the lack of precision in f[256.]. It looks like f[N[256,700]] actually works better, but I’m not yet sure how to interpret it. Sep 13, 2020 at 17:19
• Well, N[f[256]] uses exact numbers with infinite precision, f[N[256,700]] uses 700 digits of precision, and f[256.] less than 20. This should explain both the speed differences and the difference in the accuarcy of the results Sep 13, 2020 at 17:30

Clear["Global*"]

exp = n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n, 2 + n, -1];
f[n_] := n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n,
2 + n, -1]
f1[n_] := n^2/2 Gamma[n + 1/2] Hypergeometric2F1Regularized[1, 1 - n,
2 + n, -1]
f1[n] == f[n] // FullSimplify

(* True *)

{exp /. {n -> 256.}, f[256.], f1[256.], N[exp /. {n -> 256}], N[f[256]],
N[f1[256]]} // Quiet

(* {0., 109.439, 0., 109.439, 109.439, 109.439} *)


This is a precision issue with some representations (which alter the sequence of operations). Just avoid machine precision by using arbitrary-precision.

exp /. {{n -> 256.}, {n -> 256.015}, {n -> SetPrecision[256., 15]}} // Quiet

(* {0., 109.438999105, 109.438999105} *)

f1 /@ {256., 256.015, SetPrecision[256., 15]}

(* {0., 109.438999105, 109.438999105} *)

• Thanks, I wonder why the precision appears to be different when n is an argument of a function as opposed to replacement. Sep 14, 2020 at 19:12
• @level1807 That's not the issue. See my answer.
– Alan
Sep 15, 2020 at 11:45

This is fun. Let's make it even more mysterious:

Clear[n]
exp = n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n,
2 + n, -1]
"test with Block:"
Block[{n = 256.}, exp]  (* 0, with a warning *)
Block[{n = 256.},
n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n, 2 + n, -1]] (* 109.439 *)


Use Trace to see the divergence in evaluation:

Trace@Block[{n = 256.}, exp]
Trace@Block[{n = 256.},
n^2/2 Gamma[n + 1/2]/Gamma[n + 2] Hypergeometric2F1[1, 1 - n, 2 + n, -1]]


Bottom line: Use the one that does not give a warning. (And btw, you can evaluate the expression in pieces, which supports this.)

Clear[n]
expr = {n^2/2, Gamma[n + 1/2]/Gamma[n + 2], Hypergeometric2F1[1, 1 - n, 2 + n, -1]};
Times @@ (expr /. {n -> 256.})
`