Automatically add fractions and reduce the result (if neccessary)

2020-04-14: Updated to properly output case when denominator is 1.


Using How to create a random math problem in LaTeX?, the link Cramdir pointed out, we can adapt two of the solutions there to do this. One uses Euclid's algorithm, and one uses tkz-fct.

In order to be able to package both of these solutions into a macro we need to use pgfmathtruncatemacro to ensure we are working with integers as \pgfmathsetmacro is always a decimal value. Both these produce identical results.

enter image description here

Here is the MWE using Euclid's algorithm:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\makeatletter
% Use Euclid's Algorithm to find the greatest 
% common divisor of two integers.
\def\gcd#1#2{{% #1 = a, #2 = b
    \ifnum#2=0 \edef\next{#1}\else
        \@tempcnta=#1 \@tempcntb=#2 \divide\@tempcnta by\@tempcntb
        \multiply\@tempcnta by\@tempcntb  % q*b
        \@tempcntb=#1
        \advance\@tempcntb by-\@tempcnta % remainder in \@tempcntb
        \ifnum\@tempcntb=0
            \@tempcnta=#2
            \ifnum\@tempcnta < 0 \@tempcnta=-\@tempcnta\fi
            \xdef\gcd@next{\noexpand%
                \def\noexpand\thegcd{\the\@tempcnta}}%
        \else
            \xdef\gcd@next{\noexpand\gcd{#2}{\the\@tempcntb}}%
        \fi
    \fi}\gcd@next
}
\newcommand\reduceFrac[2]
{%
   \gcd{#1}{#2}{\@tempcnta=#1 \divide\@tempcnta by\thegcd
   \@tempcntb=#2 \divide\@tempcntb by\thegcd
   \ifnum\@tempcntb<0\relax
      \@tempcntb=-\@tempcntb
        \@tempcnta=-\@tempcnta
    \fi
    \xdef\rfNumer{\the\@tempcnta}
    \xdef\rfDenom{\the\@tempcntb}}%
}
\makeatother

\newcommand*{\fracReduced}[2]{%
    \reduceFrac{#1}{#2}%
    \ensuremath{%
        \ifnum\rfDenom=1
            \rfNumer
        \else
            \frac{\rfNumer}{\rfDenom}%
        \fi
    }%
}%


\newcommand{\addfraction}[4]{% 1N, 1D, 2N, 2D
    \pgfmathsetmacro{\newnumerator}{#1*#4+#3*#2}
    \pgfmathsetmacro{\newdenominator}{#4*#2}
    \pgfmathtruncatemacro{\newnumeratorTrunc}{\newnumerator}
    \pgfmathtruncatemacro{\newdenominatorTrunc}{\newdenominator}
    \pgfkeys{/pgf/number format/.cd,int detect,precision=2}
    \[ \frac{#1}{#2} + \frac{#3}{#4} 
        = \frac{\pgfmathprintnumber{\newnumerator}}{\pgfmathprintnumber{\newdenominator}} 
        = \fracReduced{\newnumeratorTrunc}{\newdenominatorTrunc} 
    \]
}

\begin{document}
\addfraction{3}{4}{1}{2}
\addfraction{3}{4}{5}{4}
\end{document}

And here is the one using tikz-fct

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usepackage{tkz-fct}

\newcommand*{\fracReducedTkz}[2]{%
    \tkzReducFrac{#1}{#2}
    \ensuremath{
        \ifnum\tkzMathSecondResult=1
            \tkzMathFirstResult
        \else
            \frac{\tkzMathFirstResult}{\tkzMathSecondResult}
        \fi
    }
}

\newcommand{\addfraction}[4]{% 1N, 1D, 2N, 2D
    \pgfmathsetmacro{\newnumerator}{#1*#4+#3*#2}
    \pgfmathsetmacro{\newdenominator}{#4*#2}
    \pgfmathtruncatemacro{\newnumeratorTrunc}{\newnumerator}
    \pgfmathtruncatemacro{\newdenominatorTrunc}{\newdenominator}
    \pgfkeys{/pgf/number format/.cd,int detect,precision=2}
    \[ \frac{#1}{#2} + \frac{#3}{#4} 
        = \frac{\pgfmathprintnumber{\newnumerator}}{\pgfmathprintnumber{\newdenominator}} 
        = \fracReducedTkz{\newnumeratorTrunc}{\newdenominatorTrunc} 
    \]
}

\begin{document}
\addfraction{3}{4}{1}{2}
\addfraction{3}{4}{5}{4}
\end{document}

The addfraction commands are identical, except the last line calls a different macro in the two examples.


Here's a LuaTeX solution for fun, in case anyone is interested. This solutions deals with negative cases and division by zero, although it need to be enclosed by $...$. Further tuning can be done with \ifmmode, though.

%!TEX program = lualatex
\documentclass{standalone}
\usepackage{luacode}
\usepackage{amsmath}
\begin{luacode*}
function gcd(a,b)
    if b ~= 0 then
        return gcd(b, a % b)
    else
        return math.abs(a)
    end
end
function sgn(a)
    if a == 0 then 
        return 0
    else 
        return a/math.abs(a)
    end 
end
function fractionadd(a,b,c,d)
    local first = a*d + b*c
    local second = b*d
    frac = first/second
    local abs = math.abs
    local afirst = abs(first)
    local asecond = abs(second)
    if second == 0 then
        return [[\text{Impossible to divide by zero}]]
    elseif gcd(afirst,asecond) == asecond then
        return math.floor(sgn(frac)*afirst/(gcd(afirst,asecond)))
    else
        return [[\frac{]]..math.floor(sgn(frac)*(afirst/gcd(afirst,asecond)))..[[}{]]..math.floor(asecond/gcd(afirst,asecond))..[[}]]
    end 
end
\end{luacode*}
\newcommand{\fractionadd}[4]{\directlua{tex.print(fractionadd(#1,#2,#3,#4))}}
\begin{document}
$\fractionadd{8}{2}{9}{3}$,
$\fractionadd{1}{2}{1}{3}$,
$\fractionadd{1}{2}{-1}{3}$.
$\fractionadd{-4}{3}{-2}{3}$,
$\fractionadd{4}{-3}{-10}{6}$,
$\fractionadd{-4}{0}{-2}{3}$,
$\fractionadd{1}{5}{-2}{11}$
\end{document}

enter image description here