Skip to content

A mixed-base exponential equation is solved with a double where an exact closed form exists #1007

Description

@Rafael-SOWNet

ExponentialSolver answers a mixed-base exponential equation with a decimal where an exact closed form exists, and the decimal is a double — so the answer is right to about 16 significant figures and wrong after that.

Measured on master at 6b93b401 (2.3.0), .NET 10, default settings.

"3^(x+1) - 2^(x-1)".ToEntity().SolveEquation("x")
// { ln(0.046745698226286304388654713193318457342684268951416015625 ^ (1 / ln(2))) }

The exact solution is -ln(6)/ln(3/2): from (x + 1) ln 3 = (x - 1) ln 2 we get x (ln 3 - ln 2) = -(ln 2 + ln 3).

value
what the library returns -4.41902258270290894605922892889481357965605673565923995921149…
-ln(6)/ln(3/2) -4.41902258270290955395238052434802828123000747047221444614890…

They agree to 17 significant figures and then diverge, which is the signature of a double that has been promoted to a decimal rather than a number that was computed exactly. 3^(x+1) - 2^(x-1) evaluated at the exact form is 0.

Where it comes from

ExponentialSolver.SolveMultiplicative (Sources/AngouriMath/Functions/Continuous/Solvers/EquationSolver/ExponentialSolver.cs, the "all bases are numerical" branch) divides each exponent by the smallest and simplifies:

var divided = (pow / minPow).InnerSimplified;
expr = expr.Substitute(MathS.Pow(x, pow.InnerSimplified), MathS.Pow(substitution, divided));

For two different integer bases that ratio is ln(3)/ln(2) — irrational — and InnerSimplified settles it to a decimal, after which everything downstream is numeric. The single-base cases never hit this, which is why 2^(2x) - 5·2^x + 4{ 0, 2 } is exact and this one is not.

Why it is worth a separate issue

Not a wrong answer, so it is not urgent by the ordering in AGENTS.md — but it is the shape that ordering warns about: the returned set is exactly as usable as its precision, and nothing about the printed form says a double went through it. It is also the same defect class as the one #918 fixed for polynomial roots, where three of five roots came back with one of them a float.

Acceptance criteria

  • 3^(x+1) - 2^(x-1) solved for x returns a form built from ln and exact rationals, with no decimal literal in it.
  • The single-base cases that are exact today stay exact: 2^x - 8{ 3 }, 2^(2x) - 5·2^x + 4{ 0, 2 }, ln(x)² - 3ln(x) + 2{ e, e² }.
  • Where no exact form exists, the solver declines or answers with the exact symbolic expression — it does not substitute a decimal for a closed form it did not find. Not answering is legitimate; answering imprecisely without saying so is the thing to avoid.
  • A test that asserts the value, by substituting the returned root back, rather than the printed text.

Found while re-measuring #214 for #746 item 16, which is otherwise answered.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Minor bugMinor bugs that don't affect the overall computations

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions