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?

Michael Kropat
  • 677
  • 7
  • 13

2 Answers2

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}

Peter Grill
  • 223,288
  • That helps a lot. Now I just need to figure out how to turn it into a mixed fraction. – Michael Kropat May 12 '14 at 20:17
  • @MichaelKropat: Update to handle whole numbers. – Peter Grill May 12 '14 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 :) – Michael Kropat May 12 '14 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}​
Werner
  • 603,163
  • 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 May 12 '14 at 20:49
  • Very nice. I kinda expected something like this to be included in some package somewhere. – Michael Kropat May 12 '14 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? – PascalS Feb 24 '24 at 06:54
  • For everyone who has the same question... \protect in front of \dectofrac{2.25} did it :) – PascalS Feb 24 '24 at 06:59
  • 1
    @PascalS: Indeed, \caption arguments are fragile, as things may end up in the LoF/LoT, so they need \protection. – Werner Feb 24 '24 at 18:15