Skip to content

lim x->0 (1/x^2 - 1/sin(x)^2) answers NaN, which claims the limit does not exist #727

Closed

Description

@Rafael-SOWNet

lim x->0 (1/x^2 - 1/sin(x)^2) comes back NaN. The limit is -1/3:

x = 1e-2   -0.33334000
x = 1e-3   -0.33333340
x = 1e-4   -0.33333333

NaN is not "unevaluated" here -- it is the claim that the limit does not exist -- so
this is a wrong answer rather than a missing one. 1/sin(x)^2 - 1/x^2 is the same, and
csc(x)^2 - 1/x^2 returns unevaluated where it is 1/3.

"1/x^2 - 1/sin(x)^2".ToEntity().Limit("x", 0)   // NaN, want -1/3
"1/sin(x)^2 - 1/x^2".ToEntity().Limit("x", 0)   // NaN, want 1/3
"csc(x)^2 - 1/x^2".ToEntity().Limit("x", 0)     // unevaluated, want 1/3

The unsquared forms are right, so this is next to what
#714 fixed rather than a regression of
it: 1/x - 1/sin(x) gives 0.

Two separate causes, both in Limits/Transformations.cs:

  1. The difference does go over a common denominator, giving
    (sin(x)^2 - x^2) / (x^2 * sin(x)^2), which is an ordinary 0/0 -- but l'Hopital's
    rule refuses the first step. Its growth guard allows a quotient to grow by eight
    nodes, and this one goes 17 -> 26. That budget is what growth looks like when the
    divisor is a power of the variable, which shrinks when differentiated. A divisor that
    is a product of vanishing factors grows by the product rule instead, so the chain
    grows before it collapses -- 17 -> 26 -> 33 -> 46 -- and four steps then settle it
    at -1/3. With the guard widened the answer comes out in about 2 s.

  2. csc(x)^2 is written (1/sin(x))^2 in front of the descent, and SplitProduct does
    not look inside a power for a denominator, so that term is read as having none and
    the sum is never put over a common denominator at all.

Once l'Hopital declines, the descent substitutes each half's limit and answers
+oo - +oo, which is where the NaN comes from.

Activity

  1. Rafael-SOWNet commented on Aug 5, 2026

    @Rafael-SOWNet
    MemberAuthor

    Fixed in #728, merged to master as 0cb3249.

    Measured on master before and after:

    before after
    lim x->0 (1/x^2 - 1/sin(x)^2) NaN -1/3

    NaN here is not a missing answer -- it asserts the limit does not exist, where it is -1/3. Two causes, both fixed:

    • The l'Hopital growth guard was flat. It allowed eight nodes of growth, which is what growth looks like when the divisor is a power of the variable: differentiating shrinks it, so only the dividend grows, and it grows by addition. A divisor that is a product of vanishing factors grows by the product rule instead, so the chain grows before it collapses (17 -> 26 -> 33 -> 46 nodes) and four steps then settle it. The guard is now proportional to the input size rather than a flat count. The budget had gone stale for a reason worth recording: it was measured when nothing else bounded the rule, and the depth and application caps that came later now do most of that work.
    • SplitProduct did not look inside powers. csc(x)^2 arrives as (1/sin(x))^2, whose denominator sits inside the power, so that term was read as having no denominator and the difference was never put over a common one at all.

    Regression test in DifferenceOfFractionsTest.cs. Full suite green, 117-problem corpus unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions