5

How is the correct synatax to format in math or text?

Thanks for your help

enter image description here

\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}

\ExplSyntaxOn

\NewDocumentCommand{\quadSol}{mmm}
 {% #1 = a, #2 = b, #3 = c  in  ax^2 + bx + c
  \group_begin:
   { \thomas_quadSol_step:nnn { #1 } { #2 } { #3 } }
  \group_end:
 }

\cs_new_protected:Nn \thomas_quadSol_step:nnn
 {
   \ifnum \fp_eval:n{#2*#2-4*#1*#3} <0 {\quad Die Gleichung hat keine reellen Lösungen } 
   \else
     $x_{1}=$
     \num{ \fp_eval:n { round( (-#2+sqrt((#2)^2-4*#1*#3))/(2*#1), 2 ) } }
     \quad
     $x_{2}=$
     \num{ \fp_eval:n { round( (-#2-sqrt((#2)^2-4*#1*#3))/(2*#1), 2 ) } }
   \fi
 }

\ExplSyntaxOff

\begin{document}

\quadSol{1}{2}{5}

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

\end{document} 

2 Answers2

11

The problem is that _ is a letter in \ExplSyntaxOn. Use \sb instead. Also spaces are ignored, you have to escape them in expl3 with \. In addition, to get correct spacing don't enclose x\sb{1}= with $ but the whole line. Also you should replace \ifnum\fp_eval:n with \fp_compare:nNnTF.

\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}

\ExplSyntaxOn

\NewDocumentCommand{\quadSol}{mmm}
 {% #1 = a, #2 = b, #3 = c  in  ax^2 + bx + c
  \group_begin:
   { \thomas_quadSol_step:nnn { #1 } { #2 } { #3 } }
  \group_end:
 }

\cs_new_protected:Nn \thomas_quadSol_step:nnn
 {
  \fp_compare:nNnTF { #2*#2-4*#1*#3 } < { 0 }
    {\quad Die\ Gleichung\ hat\ keine\ reellen\ Lösungen } 
    {
     $x\sb{1}=
     \num{ \fp_eval:n { round( (-#2+sqrt((#2)^2-4*#1*#3))/(2*#1), 2 ) } }
     \quad\lor\quad
     x\sb{2}=
     \num{ \fp_eval:n { round( (-#2-sqrt((#2)^2-4*#1*#3))/(2*#1), 2 ) } }$
    }
 }

\ExplSyntaxOff

\begin{document}

\quadSol{1}{2}{5}

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

\end{document}

Note however that the algorithm you use isn't numerical stable and therefore your solutions might be wrong.

A slightly more numerical stable version of the algorithm (which takes more time and doesn't seem worth it for most examples, imho) would be:

\cs_new_protected:Nn \thomas_quadSol_stable:nnn
{
  \fp_compare:nNnTF { #2 * #2 } < { 4 * #1 * #3 }
    {\quad Die\ Gleichung\ hat\ keine\ reellen\ Lösungen } 
    {
      \fp_set:Nn \l_tmpa_fp { #2 / (2*#1) } % p in pq-formel
      \fp_set:Nn \l_tmpb_fp { #3 / #1 } % q in pq-formel
      \fp_compare:nNnTF { \l_tmpa_fp } < { 0 }
        {
          \fp_set:Nn \l_tmpa_fp
            { sqrt( \l_tmpa_fp*\l_tmpa_fp - \l_tmpb_fp ) - \l_tmpa_fp }
        }{
          \fp_set:Nn \l_tmpa_fp
            { - sqrt( \l_tmpa_fp*\l_tmpa_fp - \l_tmpb_fp ) - \l_tmpa_fp }
        }
      \fp_set:Nn \l_tmpb_fp { \l_tmpb_fp / \l_tmpa_fp }
      $x\sb{1}=
      \num{ \fp_eval:n { round( \l_tmpb_fp , 2 ) } }
      \quad\lor\quad
      x\sb{2}=
      \num{ \fp_eval:n { round( \l_tmpa_fp , 2 ) } }$
    }
}
Skillmon
  • 60,462
  • Btw: You could really replace \ifnum by \int_compare... – TeXnician Nov 07 '17 at 12:32
  • @TeXnician you're right, didn't thought of checking other control sequences. – Skillmon Nov 07 '17 at 12:33
  • @TeXnican, this is good idea. But how can I find all this commands? –  Nov 07 '17 at 12:34
  • 3
    @Thomas If you use expl3 you should definitely know interface3.pdf. – TeXnician Nov 07 '17 at 12:34
  • @Skillmon I changed “can” into “should”. It could be \int_compare:nNnTF, but only if integers are supposed to be given as argument. – egreg Nov 07 '17 at 12:45
  • @egreg should I implement a numerical stable version of calculating the solution? – Skillmon Nov 07 '17 at 13:04
  • @Skillmon I don't think so; actually, accurate computations are better done with other tools. – egreg Nov 07 '17 at 13:05
  • @TeXnican thanks for the hint with the file interface3.pdf –  Nov 07 '17 at 14:09
  • @Skillmon the calculation does not require much accuracy, but if it were not a big hassle, I would be interested in a numerically stable solution. –  Nov 07 '17 at 14:12
  • @Thomas actually it is only important in unlikely situations where there might be extinctions, in your example it doesn't make a difference. And for example with \quadSol{1}{200}{1} the better accuracy are 4 decimal places of 16. I don't think it is worth it. Anyway, see my update (but remember what egreg wrote about "better done with other tools"). – Skillmon Nov 07 '17 at 15:20
  • @Skillmon at the end you say "But it doesn't seem to be better in TeX" but this sounds ambiguous as you are actually referring to a specific math engine (actually quite obedient to IEEE-754 et al standards), in particular using about 16 decimal digits precision. One can do arbitrary precision too in TeX ! –  Nov 07 '17 at 17:23
  • @jfbu Whoops, seems like I compared the stable with round(x,2) with the unstable version without the round function. My bad, I'll update my answer. – Skillmon Nov 07 '17 at 18:31
4

I know my answer is slightly off-topic. However there was in comments to main answer some discussion about numerical stability. With xint which computes algebra exactly you don't have to worry about whether some subtraction will induce lost digits; sure the square-root must be approximated but once done, all other computations being exact need no tricks about how to do the algebra best.

The second point is that there is a difficulty with siunitx's \num parsing being done before expansion of its argument. I had no such problem with for example \numprint macro from numprint package. So second point of answer is to explain how to use siunitx's \num with arguments evaluated via xint computations.

\documentclass[ngerman]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{siunitx}
\usepackage{xintexpr}

% workaround problem with siunitx \num parsing before expanding
% workaround done in a way allowing \num's optional parameters
\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}}
% for example something like
% \numx[scientific-notation=true]{\xinttheiexpr[#1] x2\relax}
% in code below would work.

% when using numprint's \np I encountered no problem like the \num's ones
% no workaround as in the above appeared necessary then
% \usepackage[autolanguage, np]{numprint}
% \let\numx\np

\newcommand\quadSol[4][2]{%
% #1 = user specified fixed point precision for rounding the output
% #2 = a, #3 = b, #4 = c  in  ax^2 + bx + c
% IT IS ASSUMED a IS NOT ZERO
  Die Gleichung mit $a=#2$, $b=#3$, $c=#4$ hat
  \begingroup
%
% \xintdefvar does computations exactly with rational numbers
% the sqrt(x) function computes with the prevailing float
% precision set by \xintDigits. Default: 16 decimal digits.
% one can also do sqrt(x, P) for using another precision.
%
% \xinttheiexpr[N] does exact computation like \xintdefvar
% or \xinttheexpr, but it rounds final result to N decimal digits
% after decimal mark. There is no removal of trailing
% zeroes (this should be job of formatting macro).
% 
    \xintdefvar a := #2;%
    \xintdefvar b := #3;%
    \xintdefvar c := #4;%
    \xintdefvar Delta := b*b - 4a*c;%
    \xintifSgn{\xinttheexpr sgn(Delta)\relax}
       {keine reellen Lösungen.}
       {eine doppelte Lösung
            ${}\approx\numx{\xinttheiexpr[#1] -b/2a\relax}$.}
       {zwei Lösungen
% We don't have to worry about numerical unstability because
% \xintdefvar (contrarily to \xintdeffloatvar) computes exactly!
% All the "loss" is in the square-root...
% By the way, let's compute it once only
% (use sqrt(Delta, P) for other precision P).
        \xintdefvar sqrtDelta := sqrt(Delta);% 
% The order x1, x2 is chosen to get x1 < x2 if a>0
        \xintdefvar x1 := (-b-sqrtDelta)/2a;%
        \xintdefvar x2 := (-b+sqrtDelta)/2a;%
%
% if we had been worried about numerical stability, we would have first
% defined x1 (if b>0) then get x2 by c/a/x1 formula.
% 
% but we are not worried because we compute exactly...
% once the square root is approximated as a floating point number (by default
% with 16 digits of precision).
%
% Raw output from \xinttheexpr can not be fed to \num as it is in A/B[X]
% format. So we use \xinttheiexpr[N] (fixed-point) or \xintthefloatexpr[N]
% (floating-point, uses scientific notation only if exponent is out of
%  -5,..,5 range as in Maple output).
%
        $x_{1}\approx \numx{\xinttheiexpr[#1] x1\relax}$
        and 
        $x_{2}\approx \numx{\xinttheiexpr[#1] x2\relax}$.
  %\par
  % Their sum is 
  %       $x_1 + x_2 \approx \numx{\xinttheiexpr[#1] x1 + x2\relax}$, and their product
  %       ix $x_1 x_2 \approx \numx{\xinttheiexpr[#1] x1*x2\relax}$.
}%
  \endgroup\par\medskip
}

\begin{document}

\quadSol{1}{2}{5}

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

\quadSol{1}{200}{1}

\quadSol[12]{1}{200}{1}

\quadSol{1}{10000}{1}

\quadSol[12]{1}{10000}{1}

% \quadSol{1}{-\xinttheiexpr[2] 1.73+3.27\relax}{\xinttheiexpr[4] 1.73*3.27\relax}

\end{document}

enter image description here

  • s/and/und/g... –  Nov 08 '17 at 10:59
  • thank you for your slightly off-topic answer. I have already noticed that your package xint is very powerful. And thank you for explaining why there are problems with the num-macro. –  Nov 08 '17 at 12:36
  • @Thomas thanks for kind words. Unfortunately xint currently only knows square root... (I am planning to extend it, but already delayed 2 years doing it). The num macro must have its reasons for not expanding its argument before it parses it. One only needs to be aware of it so that one uses a variant macro which does this expansion if it is needed. –  Nov 08 '17 at 12:54
  • I wish you enough muse to make good progress with your extension of your xint package. I use some of your examples in a modified form for my admittedly simple calculations, as they are needed at German grammar schools. Thanks for that. –  Nov 08 '17 at 13:13