# Automated solution of a quadratic equation with non approximated solution

How to get the roots automatically not in an approximate way but with square roots in Output format for text and math with macro not correct ?

(editor's update) I.e., I need a LaTeX macro \quadSol with (at least) three arguments being the coefficients a, b, c of ax^2+bx+c and which will compute the solutions exactly as rationals if possible, and if not express them with some radical for example 1+\sqrt{3} and 1-\sqrt{3}, and then also typeset some approximation. The supported coefficients a, b, c will at minimal be integers, better if also (small) decimal numbers and fractions are accepted. This is for automatic generation of school exercises, so the number of digits in coefficients will be small. (the coefficients will not themselves be irrationalities).

• -@David Carlisle thanks for your hint. – user139826 Nov 11 '17 at 7:01

For this follow-up question to Output format for text and math with macro not correct, I re-visited my answer to Simplifying square roots.

• re-factored the \ExtractRadical macro to address a remark I had made in Simplifying square roots

• simplified \quadSol to benefit from the fact that xint 1.2p allows silmutaneous assignments.

Code

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse}
\usepackage{siunitx}
\usepackage{geometry}
\sisetup{group-separator={\,},output-decimal-marker={,}}

\usepackage{xintexpr}

% To use \num of siunitx with \xinttheiexpr...\relax kind of things
% as argument
\newcommand\numx[]{\begingroup\if\relax\detokenize{#1}\relax
\def\x{\endgroup\num}\else
\def\x{\endgroup\num[#1]}\fi
\expandafter\x\expandafter{\romannumeral-0#2}}

% ------------------------

% It outputs A,B for input N in order for
%         N = A^2 * B, B square-free

% Algorithm initially from https://tex.stackexchange.com/a/300097/4686
% but now improved to have a more efficient test for breaking the loop.

% https://tex.stackexchange.com/questions/300035/simplifying-square-roots#comment726934_300097

% main variable is a quadruple P, I, J, K
%  - always N = I^2 J
%  - P is odd integer, except at start, P=2
%  - I is divisible only by primes < P
%  - K is J freed from primes < P
% initialization: 2, 1, N, N
% variables at each iteration: P, I, J, K
% Q=P^2
% is Q > K ?
%   - yes: return I, J
%   - no:
%         does Q divide J ?
%           if yes: repeat I=I*P, J=J/Q, K=K/Q until Q does not divide J
%
%         then if P divides K, set K = K/P
%         and continue with (P+2, I, J, K).
% Except if P=2 then we go on with P=3.

% Also works with N=0 (produces 1, 0) and with N=1 (produces 1, 1)

% This implementation uses only \numexpr and is thus limited to integers <
% 2^31.

\makeatletter

\romannumeral0%
\expandafter
}%
}%
\ifnum\numexpr#1*4=#3
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
\the\numexpr\ifodd #3 #3\else#3/2\fi;#2,#3.}%
}%
% P, K; I, J.
}%
% P^2.P, K; I, J.
{%
\expandafter
}%
% I//P^2.P^2,P;I, J;K.
\ifnum\numexpr#1*#2=#5
\else
\fi
#1.#2,#3;#4,#5;%
}%
\the\numexpr#1/#2\expandafter.%
\the\numexpr#2\expandafter,%
\the\numexpr#3\expandafter;%
\the\numexpr#3*#4\expandafter,%
\the\numexpr#1\expandafter;\the\numexpr#6/#2.%
}%
\the\numexpr2+#3\expandafter,%
\the\numexpr\ifnum\numexpr(#5/#3)*#3=#5
#6/#3\else #6\fi;#4,#5.%
}%

% An auxiliary macro
% ------------------

% we need this to separate numerator and denominator of fractions inside an
% xintexpr. There is no function for that in xintexpr syntax, so far.

\newcommand\NumAndDenom{\expandafter\@NumAndDenom\romannumeral-0#1;}
\def\@NumAndDenom #1/#2;{#1,#2}
\makeatother

% ----------------------

% REMARK: use of single letter variable with \xintdefvar is quite dangerous
% because they are also used as dummy letters in \xintexpr syntax. So if the
% code here uses an external macro itself using \xintexpr, there might
% be a clash.
%
% Currently the world is not overwhelmed
% with \xintexpr based code, but if that happens one day...
% ... better stop using single-letter names like here a, b, c, L, A, B,
% U, V, W ... this is very dangerous if using an external expandable macro
% which was written in \xintexpr syntax. As a rule, always use multi-letter
% identifiers with \xintdefvar... (do what I say, not what I do...)
%
\begingroup
% simultaneous assignments require xint 1.2p 2017/12/05 ...
\xintdefvar a, b, c := #1, #2, #3;%
\xintdefvar Delta := b*b - 4a*c;%
\xintifSgn{\xinttheexpr sgn(Delta)\relax}
{keine reellen Lösungen.\par}
{eine doppelte Lösung
% see documentation of typesetting macro \xintFrac in xint.pdf
$\xintFrac{\xinttheexpr reduce(-b/2a)\relax}$.\par
}
{zwei Lösungen
% Use \NumAndDenom macro defined above to assign numerator to A, denom to B
% simultaneous assignments require xint 1.2p 2017/12/05 ...
\xintdefiivar A, B := \NumAndDenom{\xintIrr{\xinttheexpr Delta\relax}};%
% some student exercises will be cooked up to have rational solution
% hence a discriminant being an exact square in rational numbers, so we
% first check for them even though it adds a bit of overhead to general
% case where discriminant will not be perfect square.
\xintdefiivar rA, rB := sqrt(A), sqrt(B);% truncation of exact square root
\xintifbooliiexpr{A == rA**2 && B == rB**2}
{%\perfectsquaretrue
\xintdefvar sqrtDelta := sgn(a)*rA/rB;% sgn(a) trick to get x1 < x2
\xintdefvar x1, x2:= reduce((-b-sqrtDelta)/2a),
reduce((-b+sqrtDelta)/2a);%
$x_{1}= \xintFrac{\xinttheexpr x1\relax}$
und
$x_{2}= \xintFrac{\xinttheexpr x2\relax}$.\par
}%
{%\perfectsquarefalse
% we decompose numerator and denominator as (x^2)*y with y square free
% This is done using expandable \ExtractRadical macro defined above.
\xintdefvar rA, sqfreeA := \ExtractRadical{\xinttheiiexpr A\relax};%
\xintdefvar rB, sqfreeB := \ExtractRadical{\xinttheiiexpr B\relax};%
\xintdefvar U := reduce(-b/2a);%
%
\xintdefvar V := abs(reduce(1/2a*rA/rB));% V > 0
\xintdefvar W := sqfreeA/sqfreeB;% irreducible, W > 0
\xintdefvar sqrtW := sqrt(W);% computed with \xinttheDigits digits
% The order x1, x2 is chosen so that x1 < x2 always
\xintdefvar x1, x2 := U - V*sqrtW, U + V*sqrtW;%
$x_{1} = \xintFrac{\xinttheexpr U\relax} - \xintFrac{\xinttheexpr V\relax}\times \sqrt{\xintFrac{\xinttheexpr W\relax}} \approx \numx{\xinttheiexpr x1\relax}$
und
$x_{2} = \xintFrac{\xinttheexpr U\relax} + \xintFrac{\xinttheexpr V\relax}\times \sqrt{\xintFrac{\xinttheexpr W\relax}} \approx\numx{\xinttheiexpr x2\relax}$.\par
}%
}%
\endgroup
}

#1 -> \xinttheiiexpr Ipart, Jpart\relax\
(\xinttheiiexpr Ipart**2 * Jpart\relax =\the\numexpr#1\relax)\par
}
\begin{document}

\ttfamily

\bigskip

\rmfamily

\bigskip

\bigskip

\bigskip

\bigskip

\bigskip

\bigskip

\bigskip

% \bigskip

% too big for \numexpr,

% \bigskip

\bigskip

\bigskip

\bigskip 