4

I'm creating an invoice in LaTeX and I've entered the hours I've worked as decimals (for example, 1, 1.5, 0.75, 2.25), but I want to display those decimals as fractions (1, 1½, ¾, 2¼).

(The reason I've entered the hours worked as a decimal is so I can perform simple invoice math with the fp package along the lines of this answer)

For a little context, here's the synopsis of the macro I created that includes the number of hours worked:

\lineitem{DATE}{HOURS}{RATE}{PROJECT}{DESCRIPTION}

The conversions I have in mind are pretty simple:

tex rendered

\documentclass{article}
\usepackage{xfrac}
\begin{document}
\begin{tabular}{r @{} l | r @{\hspace{0.1em}} l}
\multicolumn{2}{c}{Given...} & \multicolumn{2}{c}{Output} \\
\hline
1 & & 1 & \\
1 & .5 & 1 & \sfrac{1}{2} \\
0 & .75 & \sfrac{3}{4} & \\
2 & .25 & 2 & \sfrac{1}{4} \\
\end{tabular}
\end{document}

(I'm not married to \sfrac for displaying fractions, it's just the first package I reached for)

Is there an off-the-shelf package that will do what I want? If not, can anyone give me a few pointers how I might go about implementing my own conversion/display logic?

2

2 Answers 2

4

Adapting the solution from Automatically add fractions and reduce the result (if neccessary) yields:

enter image description here

Notes:

  • The \hphantom line should be commented out in your actual use case. It was added to produce a nicer output for posting on TeX.SE.
  • This may not yield ideal results for all possible decimals but does work for the ones requested.
  • For the HH:MM format, I used the xstring package for string comparison as I prefer its format, but probably can be done without this package if desired.

Code:

\documentclass{article}
\usepackage{tikz}
\usepackage{xfrac}
\usepackage{xstring}

\makeatletter
\newcommand*{\@PositionOfColon}{}%
\newcommand{\IfStrContains}[4]{%
    \StrPosition{#1}{#2}[\@PositionOfColon]% Record position in \@PositionOfColon
    \IfEq{\@PositionOfColon}{0}%
    {#4}% StrPosition=0 => Did not find the target string
    {#3}% StrPosition>0 => Found the target string
}%

% 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
}



%% Adapted from https://tex.stackexchange.com/questions/28628/automatically-add-fractions-and-reduce-the-result-if-neccessary
\newcommand*{\rfNumer}{}%
\newcommand*{\rfDenom}{}%
\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{\sfrac{\rfNumer}{\rfDenom}}}%



\newcommand*{\TempNumerator}{}%
\newcommand*{\TempDenominator}{}%
\newcommand*{\DecimalToFrac}[1]{%
    \IfStrContains{#1}{:}{%
        \StrBefore{#1}{:}[\WholePortion]%
        \StrBehind{#1}{:}[\TempNumerator]%
        \def\TempDenominator{60}%
    }{%
        \pgfmathtruncatemacro{\WholePortion}{int(#1)}%
        \pgfmathtruncatemacro{\TempNumerator}{100*(#1-\WholePortion)}%
        \def\TempDenominator{100}%
    }%
    #1 =
    \ifnum\WholePortion > 0\relax%
        \WholePortion%
    \else
        \hphantom{0}% Just for nicer output of MWE. Should be deleted in actual use
    \fi
    \fracReduced{\TempNumerator}{\TempDenominator}%
}%

\begin{document}
Using decimals:

\DecimalToFrac{0.75},
\quad
\DecimalToFrac{0.50},
\quad
\DecimalToFrac{0.25}.

\DecimalToFrac{2.75},
\quad
\DecimalToFrac{1.50},
\quad
\DecimalToFrac{3.25}.

\bigskip
Using \texttt{HH:MM} format:

\DecimalToFrac{0:45},
\quad
\DecimalToFrac{0:30},
\quad
\DecimalToFrac{0:15},

\DecimalToFrac{0:20},
\quad
\DecimalToFrac{0:10},
\quad
\DecimalToFrac{0:05}.

\medskip
\DecimalToFrac{2:45},
\quad
\DecimalToFrac{1:15},
\quad
\DecimalToFrac{3:10}.

\DecimalToFrac{2:20},
\quad
\DecimalToFrac{1:10},
\quad
\DecimalToFrac{3:05}.
\end{document}
3
  • That helps a lot. Now I just need to figure out how to turn it into a mixed fraction. Commented May 12, 2014 at 20:17
  • @MichaelKropat: Update to handle whole numbers. Commented May 12, 2014 at 20:29
  • That works beautifully. The code is about what I expected, except that it would have taken me forever to figure out how to express that on my own, so thanks a bunch. That was the last piece of my invoice, so now I can finally get paid, hopefully :) Commented May 12, 2014 at 20:41
3

tikz provides this type of formatting:

enter image description here

\documentclass{article}
\usepackage{tikz,xfrac}
\usetikzlibrary{fpu}
\newcommand{\dectofrac}[1]{\begingroup%
  \pgfkeys{/pgf/number format/frac}% Format as fraction
  \let\frac\sfrac% Let \frac act like \sfrac
  \pgfmathprintnumber{#1}\endgroup}
\pagestyle{empty}
\begin{document}

\begin{tabular}{r @{} l | r @{\hspace{0.1em}} l}
  \multicolumn{2}{c}{Given...} & \multicolumn{2}{c}{Output} \\
  \hline
  1&    & 1& \\
  1&.5  & 1&\dectofrac{0.5} \\
  0&.75 &  &\dectofrac{0.75} \\
  2&.25 & 2&\dectofrac{0.25}
\end{tabular}
\end{document}​
5
  • You can also use \dectofrac{2.25} which will be formatted to 2 1/4, but it depends on how you want the alignment to be.
    – Werner
    Commented May 12, 2014 at 20:49
  • Very nice. I kinda expected something like this to be included in some package somewhere. Commented May 12, 2014 at 20:51
  • @Werner Great solution! I would like to use the result within a figure caption. But this is not compilable anymore. Can you give me a hint?
    – Pascal
    Commented Feb 24 at 6:54
  • For everyone who has the same question... \protect in front of \dectofrac{2.25} did it :)
    – Pascal
    Commented Feb 24 at 6:59
  • 1
    @PascalS: Indeed, \caption arguments are fragile, as things may end up in the LoF/LoT, so they need \protection.
    – Werner
    Commented Feb 24 at 18:15

You must log in to answer this question.

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