具有非近似解的二次方程的自动解

具有非近似解的二次方程的自动解

如何自动获得根,不是以近似方式,而是以平方根带有宏的文本和数学输出格式不正确

(编辑更新)即,我需要一个 LaTeX 宏\quadSol,它至少有三个参数,分别是a, b, c和的系数ax^2+bx+c,如果可能的话,它将计算出精确的有理数解,如果不能,则用一些根式(例如1+\sqrt{3}和)来表示它们1-\sqrt{3},然后排版一些近似值。支持的系数a, b, c至少是整数,如果也接受(小)小数和分数就更好了。这是为了自动生成学校练习,因此系数中的位数会很少。(系数本身不会是无理数)。

答案1

对于这个后续问题带有宏的文本和数学输出格式不正确,我重新审视了我的回答简化平方根

答案已更新:

  • 重新考虑了\ExtractRadical宏,以解决我在简化平方根

  • 简化\quadSol以受益于 xint1.2p允许同时分配的事实。

代码

\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[12]...\relax kind of things
% as argument
\newcommand\numx[2][]{\begingroup\if\relax\detokenize{#1}\relax
                       \def\x{\endgroup\num}\else
                       \def\x{\endgroup\num[#1]}\fi
                    \expandafter\x\expandafter{\romannumeral-`0#2}}

% Macro \ExtractRadical{N}
% ------------------------

% 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

\newcommand\ExtractRadical[1]{%
    \romannumeral0%
    \expandafter
    \ExtractRadical@two@i\expandafter1\expandafter,\the\numexpr#1.%
}%
\def\ExtractRadical@two@i #1,#2.{%
    \ifnum4>#2 \expandafter\ExtractRadical@two@done\fi
    \expandafter\ExtractRadical@two@ii\the\numexpr#2/4;#1,#2.%
}%
\edef\ExtractRadical@two@done #1;#2,#3.{ #2,#3}%
\def\ExtractRadical@two@ii #1;#2,#3.{%
    \ifnum\numexpr#1*4=#3 
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
   {\expandafter\ExtractRadical@two@i\the\numexpr2*#2,#1.}%
   {\expandafter\ExtractRadical@h
    \the\numexpr\ifodd #3 #3\else#3/2\fi;#2,#3.}%
}%
\def\ExtractRadical@h {\ExtractRadical@j 9.3,}%
% P, K; I, J.
\def\ExtractRadical@i #1,{%
    \expandafter\ExtractRadical@j\the\numexpr#1*#1.#1,%
}%
% P^2.P, K; I, J.
\def\ExtractRadical@j #1.#2,#3;#4,#5.%
{%
    \ifnum#1>#3 \expandafter\ExtractRadical@done\fi
    \expandafter
    \ExtractRadical@k \the\numexpr #5/#1.#1,#2;#4,#5;#3.%
}%
\def\ExtractRadical@done #1.#2,#3;#4,#5;#6.{ #4,#5}%
% I//P^2.P^2,P;I, J;K.
\def\ExtractRadical@k #1.#2,#3;#4,#5;{%
    \ifnum\numexpr#1*#2=#5
      \expandafter\ExtractRadical@again
    \else
      \expandafter\ExtractRadical@next
    \fi
    #1.#2,#3;#4,#5;%
}%
\def\ExtractRadical@again #1.#2,#3;#4,#5;#6.{%
    \expandafter\ExtractRadical@k
    \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.%
}%
\def\ExtractRadical@next #1.#2,#3;#4,#5;#6.{%
    \expandafter\ExtractRadical@i
    \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[1]{\expandafter\@NumAndDenom\romannumeral-`0#1;}
\def\@NumAndDenom #1/#2;{#1,#2}
\makeatother


% Exact Quadratic solver
% ----------------------

\newcommand\quadSol[3]{%
% 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[12] x1\relax}$
       und
       $x_{2} = \xintFrac{\xinttheexpr U\relax}
              + \xintFrac{\xinttheexpr V\relax}\times
                    \sqrt{\xintFrac{\xinttheexpr W\relax}}
             \approx\numx{\xinttheiexpr[12] x2\relax}$.\par
      }%
     }%
  \endgroup
}

\newcommand\TestExtractRadical[1]{%
  \xintdefiivar Ipart, Jpart := \ExtractRadical{#1};%
  #1 -> \xinttheiiexpr Ipart, Jpart\relax\
       (\xinttheiiexpr Ipart**2 * Jpart\relax =\the\numexpr#1\relax)\par
}
\begin{document}

\ttfamily

\TestExtractRadical{0}

\TestExtractRadical{1}

\TestExtractRadical{64}

\TestExtractRadical{128}

\TestExtractRadical{256}

\TestExtractRadical{1024}

\TestExtractRadical{2048}

\TestExtractRadical{72}

\TestExtractRadical{360}

\TestExtractRadical{504}

\TestExtractRadical{1690}

\TestExtractRadical{2*2*2*3*3*3*5*5*5*7*7*7*11}

\TestExtractRadical{2*2*2*3*3*3*7*7*7*19*17*17}

\bigskip

\rmfamily

\quadSol{1}{2}{-1}

\bigskip

\quadSol{39}{-34}{7}

\bigskip

\quadSol{-39}{34}{-7}

\bigskip

\quadSol{39}{-35}{7}

\bigskip

\quadSol{38}{-34}{7}

\bigskip

\quadSol{1}{-10}{1}

\bigskip

\quadSol{1}{-100}{1}

\bigskip

% \quadSol{1}{-1000}{1}

% \bigskip

% \quadSol{1}{-100000}{1} 
% too big for \numexpr,

% \bigskip

\quadSol{1}{-13/5-5/13}{1}

\bigskip

\quadSol{1}{-101/99-31/16}{101/99*31/16}

\bigskip

\quadSol{1}{-2*355/113}{(355/113)**2}

\bigskip

\quadSol{1.3}{2.5}{0.9}

\thispagestyle{empty}

\end{document}

在此处输入图片描述

相关内容