13

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)?

14

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.

| improve this answer | |
  • Yay, it works nicely. Additional respect and gratitude for answering speed ;) – Tom Bombadil Sep 16 '11 at 3:52
  • It seems to crash if one of the values is negative. Or is that just on my machine? – HTG Nov 5 '12 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. – Peter Grill Nov 5 '12 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 at 8:30
  • @PeterGrill: \pgfmathprintnumber{20.0} also gives 20/1!! (by \pgfkeys{/pgf/number format/.cd,frac, frac whole=false}) – user108724 Apr 14 at 8:45
2

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

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.