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}

output

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

up vote 22 down vote accepted

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.~
    Please~provide~input~in~the~form~of~`p/q'.
  }

\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}
  • 2
    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
  • 2
    @SeanAllred \use:n? – Manuel Jul 6 '15 at 12:22
  • 1
    @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
   \advance\denominator by -\numerator
   \gcd=\denominator
 \else
   \advance\numerator by -\denominator
   \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}
  • 1
  • 2
    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. – jfbu Aug 29 '15 at 17:38
  • @jfbu You could add your answer. – Manuel Aug 29 '15 at 20:36
  • @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). – jfbu 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}

Original answer

\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

Mathematica graphics

references http://rosettacode.org/wiki/Greatest_common_divisor#Lua and http://www.lua.org/manual/5.3/manual.html

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:

enter image description here

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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