Reducing fractions automatically using LaTeX 3

Consider the following code:

\documentclass{article}

\begin{document}

\noindent Can I make \LaTeX{} reduce a fraction automatically?\$\baselineskip] For example, I would like the fraction \[ \frac{278\,922}{74\,088}$
to be reduced to
$\frac{6641}{1764}$

\end{document}


P.S. The numerator and denominator are always both natural numbers in my case.

An expl3 implementation:

\nonstopmode \input expl3-generic \relax \ExplSyntaxOn % -*- expl3 -*-

\cs_new:Nn \svend_gcd:nn
{
\int_compare:nNnTF {#2} = { 0 } {#1}
{ \svend_gcd:ff {#2} { \int_mod:nn {#1} {#2} } }
}
\cs_generate_variant:Nn \svend_gcd:nn { ff }

\int_new:N \l__svend_tmp_int
\cs_new:Nn \svend_reduced:nn
{
\int_set:Nn \l__svend_tmp_int { \svend_gcd:nn {#1} {#2} }
{ \int_eval:n { #1 / \l__svend_tmp_int } }
\over
{ \int_eval:n { #2 / \l__svend_tmp_int } }
}

$$\svend_reduced:nn {278922} {74088}$$

\bye


LaTeX version:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
% ... code code code

\msg_new:nnn { svend } { malformed-fraction }
{
The~input~you~have~provided~is~malformed.~
Please~provide~input~in~the~form~of~p/q'.
}

\NewDocumentCommand \ReducedFraction { > { \SplitList { / } } m }
{
\int_compare:nTF { \tl_count:n {#1} = 2 }
{ \svend_reduced:nn #1 }
{ \msg_error:nn { svend } { malformed-fraction } }
}

\ExplSyntaxOff

\begin{document}
$\ReducedFraction{278922/74088}$
\end{document}


Edit with wrapper

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\cs_new:Nn \svend_gcd:nn
{
\int_compare:nNnTF {#2} = { 0 } {#1}
{ \svend_gcd:ff {#2} { \int_mod:nn {#1} {#2} } }
}
\cs_generate_variant:Nn \svend_gcd:nn { ff }

\int_new:N \l__svend_tmp_int
\cs_new:Nn \svend_reduced:nn
{
\int_set:Nn \l__svend_tmp_int { \svend_gcd:nn {#1} {#2} }
\frac { \svend_reduced_wrap:n { \int_eval:n { #1 / \l__svend_tmp_int } } }
{ \svend_reduced_wrap:n { \int_eval:n { #2 / \l__svend_tmp_int } } }
}
\cs_new:Nn \svend_reduced_use_wrapper:N
{ \cs_set_eq:NN \svend_reduced_wrap:n #1 }
\svend_reduced_use_wrapper:N \use:n

%%% Interface

\msg_new:nnn { svend } { malformed-fraction }
{
The~input~you~have~provided~is~malformed.~
}

\NewDocumentCommand \ReducedFractionWrapper { m }
{ \svend_reduced_use_wrapper:N #1 }

\NewDocumentCommand \ReducedFraction { o > { \SplitList { / } } m }
{
\group_begin:
\IfValueT{#1}{\ReducedFractionWrapper{#1}}
\int_compare:nTF { \tl_count:n {#2} = 2 }
{ \svend_reduced:nn #2 }
{ \msg_error:nn { svend } { malformed-fraction } }
\group_end:
}
\ExplSyntaxOff

\usepackage{siunitx}
\begin{document}
$\ReducedFraction[\num]{278922/74088}$

\ReducedFractionWrapper{\num}

$\ReducedFraction{27892/74088}$
\end{document}

• I'd use \svend_gcd:ff in the inner calls (define a variant), or the arguments will grow up at each recursion. At one stage, the second argument to \svend_gcd:nn in your example is \int_mod:nn {\int_mod:nn {278922}{74088}}{\int_mod:nn {74088}{\int_mod:nn { 278922}{74088}}} – egreg Jul 5 '15 at 9:24
• The example computation requires just a few steps, but with, say, 100 of them,… It's a performance problem: with the present code you're continuously redoing computations you've already made. – egreg Jul 5 '15 at 15:24
• @SvendTveskæg Compile with plain TeX. – Manuel Jul 6 '15 at 11:07
• @SeanAllred \use:n? – Manuel Jul 6 '15 at 12:22
• @SvendTveskæg Yes :) I really recommend reading up on expl3, though (texdoc interface3 is also invaluable). When it comes right down to it, it's still TeX. – Sean Allred Jul 6 '15 at 12:44

Here is a flat LaTeX2e implementation.

\documentclass{article}
\usepackage{amsmath}

\newcount{\numerator}
\newcount{\denominator}
\newcount{\gcd}

% compute \gcd and returns reduced \numerator and \denominator
\newcommand{\reduce}[2]% #1=numerator, #2=denominator
{\numerator=#1\relax
\denominator=#2\relax
\loop
\ifnum\numerator<\denominator
\gcd=\denominator
\else
\gcd=\numerator% swap
\fi
\ifnum\gcd>1 \repeat
\ifnum\gcd=0 \gcd=\denominator\fi
\numerator=#1\relax
\divide\numerator by \gcd
\denominator=#2\relax
\divide\denominator by \gcd
}

\begin{document}

For example, I would like the fraction
\begin{equation*}
\frac{278922}{74088}
\end{equation*}
to be reduced to\reduce{278922}{74088}
\begin{equation*}
\frac{\the\numerator}{\the\denominator} =
\frac{6641}{1764}
\end{equation*}

\end{document}


If you are not bound to expl3 (in which case you “just” need to implement the algorithm):

\documentclass{scrartcl}
\usepackage{xintgcd,xintfrac}

\newcommand*\reducedfrac[2]
{\begingroup
\edef\gcd{\xintGCD{#1}{#2}}%
\frac{\xintNum{\xintDiv{#1}{\gcd}}}{\xintNum{\xintDiv{#2}{\gcd}}}%
\endgroup}

\begin{document}
$\frac{278922}{74088} = \reducedfrac{278922}{74088}$
\end{document}

• command \xintIrr from xintfrac (no need then to load extra package xintgcd) does the job: \xintIrr{278922/74088} expands to 6641/1764. To typeset as a TeX fraction, there is typesetting macro \xintFrac (using LaTeX's \frac under the hood), thus \newcommand*\reducedfrac [2]{\xintFrac{\xintIrr{#1/#2}}} should do the job. – user4686 Aug 29 '15 at 17:38
• @Manuel I would if the question made it clear that numbers with more than ten digits (or decimal mark and decimal digits) were involved ... yours is perfectly fine and sufficient and there are already quite a few other answers. Slightly simpler: \frac{\xintNum{#1/\gcd}}{\xintNum{#2/\gcd}}, and, again assuming that #1 and #2 are guaranteed to be given as integers, \xintiiGCD has less overhead than \xintGCD (the latter accepts fractional inputs which it truncates to integers). – user4686 Aug 29 '15 at 20:58

An option using Lua+LaTeX.

Made small improvement. Made a Lua function to be called as a LaTeX command, with the numerator and denominator passed as arguments, instead of hardcoding the values in as before. The command is \simplify{a}{b}:

\documentclass{article}
\usepackage{luacode}
\usepackage{amsmath}
%------------------------
\begin{luacode}
function simplify(a,b)
local function gcd(a,b)
if b ~= 0 then
return gcd(b, a % b)
else
return math.abs(a)
end
end

t = gcd(a, b)
tex.print("\\frac{"..a/t.."}{"..b/t.."}")
end
\end{luacode}
\newcommand\simplify[2]{\directlua{simplify(#1,#2) }}%
%-------------------
\begin{document}
\noindent Can I make \LaTeX{} reduce a fraction automatically?\\[\baselineskip]
For example, I would like the fraction
\begin{equation*}
\frac{278\,922}{74\,088}
\end{equation*}

to be reduced to

\begin{equation*}
\simplify{278922}{74088}
\end{equation*}
\end{document}


\documentclass{article}
\usepackage{luacode}
\usepackage{amsmath}

\begin{document}

\noindent Can I make \LaTeX{} reduce a fraction automatically?\\[\baselineskip]
For example, I would like the fraction
\begin{equation*}
\frac{278\,922}{74\,088}
\end{equation*}
to be reduced to
%------------------------------------
\begin{luacode*}
function gcd(a,b)
if b ~= 0 then
return gcd(b, a % b)
else
return math.abs(a)
end
end
u = 278922
v = 74088
t = gcd(v, u)
tex.print("\\begin{equation*}")
tex.print("  \\frac{"..u/t.."}{"..v/t.."}")
tex.print("\\end{equation*}")
\end{luacode*}
%------------------------------------

\end{document}


lualatex foo.tex gives

Here is a solution using R for the computations and the R-package knitr to link back to the LaTeX file.

\documentclass{article}

\begin{document}
Using R with the package 'knitr' to reduce the fraction and then get both the reduced fraction but also the components of the fraction.

Note: This is a quick demo of linking R and LaTeX using the 'knitr' package. This has been run on Windows 8.1, with MikTeX 2.9, and TeXmaker 4.4.1 as the IDE. The following code is saved as \textbf{knit02.Rnw} (and this is case sensitive). With the package 'knitr' installed in R 3.1.3 you run the command: \emph{knit("knit02.Rnw")}. This will generate the file \textbf{knit02.tex} which you now compile with pdflatex and view as a pdf.

<<echo=FALSE>>=
library(MASS)
## This function is from http://stackoverflow.com/questions
## /14820029/getting-numerator-and-denominator-of-a-fraction-in-r
getfracs <- function(frac) {
tmp <- strsplit(attr(frac,"fracs"), "/")[[1]]
list(numerator=as.numeric(tmp[1]),denominator=as.numeric(tmp[2]))
}
dd<-278922
nn<-74088
x<- fractions(dd/nn)
fracs<-getfracs(x)
denom<-fracs$denominator numer<-fracs$numerator
@
\medskip

The original fraction is $\displaystyle{\frac{\Sexpr{as.integer(dd)}}{\Sexpr{as.integer(nn)}}}$.
\medskip
The reduced fraction components are \Sexpr{fracs}.
\medskip

The reduced denominator is \Sexpr{denom}.
\medskip

The reduced numerator is \Sexpr{numer}.
\medskip

And the reduced fraction is $\displaystyle{\frac{\Sexpr{denom}}{\Sexpr{numer}}}$

\end{document}


And the output using pdflatex: