15

I'm trying to figure out how to reduce fractions. Adding fractions is no problem, see this example:

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

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

\begin{document}

\addfraction{3}{4}{1}{2}

\end{document}

In the eample, the result of adding 3/4 and 1/2 is 10/8, which obviously can be reduced to 5/4. In order to do so, I tried the frac format provided by TikZ (see tikz manual section 66 "number printing"): I computed the decimal value of my fraction, and had the result returned via \pgfmathprintnumber.

This works, however only to a certain extent. Even "simple" tasks line 4/7 + 3/8 would return a denominator of 10000 and above, instead of 53/56. I also followed the directions for increasing accuracy (frac shift and \usepackage{fp}), but still no luck.

Now I know how to manually reduce fractions, you have to find the greatest common divisor. But how to do this in an automated fashion? My guess would be that something like this is buried somewhere in TikZ as it seems to be applied when using the frac format.

So it basically comes down to this: how to find the greatest common divisor of two given numbers (preferably using TikZ)?

1

2 Answers 2

15

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.

10
  • Yay, it works nicely. Additional respect and gratitude for answering speed ;) Sep 16, 2011 at 3:52
  • It seems to crash if one of the values is negative. Or is that just on my machine?
    – HTG
    Nov 5, 2012 at 2:12
  • @HTG: I can not reproduce the behavior you describe. It seems that tik-fct version has an issue if the numerator is negative, but the other version seems to be ok. Nov 5, 2012 at 2:26
  • @PeterGrill: How to get ride of 1 in denominator? e.g. \addfraction{3}{4}{1}{4} is 1/1!!
    – user108724
    Apr 14, 2020 at 8:30
  • @PeterGrill: \pgfmathprintnumber{20.0} also gives 20/1!! (by \pgfkeys{/pgf/number format/.cd,frac, frac whole=false})
    – user108724
    Apr 14, 2020 at 8:45
1

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .