16

Is it possible to detect cases where the second argument of \frac is much smaller than the first argument, and split it? Namely (I'm using a new macro name \wfrac to simplify things),

\wfrac{x}{2} % => \frac{x}{2}
\wfrac{x+y}{2} % => \frac{1}{2}\left(x+y\right)
\wfrac{\sum_{i=1}^{N} i^3}{x+y+z+t}
% => \frac{1}{x+y+z+t} \left(\sum_{i=1}^{N} i^3\right)
% => or \left(\sum_{i=1}^{N} i^3\right) / \left(x+y+z+t\right)
\wfrac{\sum_{i=1}^{N} i^3}{\sum_{i=1}^{N} i}
% => \frac{...}{...} (unchanged)

Feel free to tell me that this is a bad idea.

EDIT: As David notes in his comment, it is not clear what I define as bigger/smaller. The third example in particular features a case where the numerator is taller, but the denominator is wider. he also notes that \wfrac{x}{y} could become (x)/(y). I am building the requirements as I write the question, so feel free to tweak them at your will.

\wfrac{x}{y} should become one of \frac{x}{y}, or \frac{1}{y}(x), or (x)/(y), with ()/ scaling as appropriate. Here is one scheme that could give nice results. Denote hx, hy the heights (plus depths) of x and y; wx, wy their widths; h0 and w0 customizable thresholds for what is considered "small", for instance the dimensions of the formula $a+b$, but probably the threshold should depend on the \mathstyle.

  1. If hy < h0 and wy < w0,

    1. If hx < h0 and wx < max(w0, 2 * wy), use \frac{x}{y}.
    2. Otherwise use \frac{1}{y}(x).
  2. Otherwise use (x)/(y).

5
  • 3
    Is there something wrong with simply boxing up the top and bottom and then measuring them?
    – Joseph Wright
    Aug 1, 2012 at 16:23
  • Hmm, seems useful, maybe it can be merged into xfrac if possible. How about put the two args into boxes and measure them?
    – Leo Liu
    Aug 1, 2012 at 16:24
  • What's the criterion for "much smaller"? In the third example with cm fonts and textsyle setting, the denominator is wider than the numerator but you still split. (If splitting because something is big I think I'd favour changing to (#1)/(#2) rather than \frac{1}{#2}(#1) as it avoids cramping either argument. Aug 1, 2012 at 16:35
  • @DavidCarlisle I tried to clarify my mind. Admittedly this is still not a good question. Aug 1, 2012 at 17:08
  • @barbarabeeton Thanks for the new title, I updated it somewhat toward what you propose. Aug 1, 2012 at 17:52

1 Answer 1

8

I though this was an interesting question, so I gave it a try.
Let me start off with the result:

main.tex:

\documentclass{article}
\usepackage{wfrac}

\begin{document}
\setmaxeq{a+b} % Reference equation for size

\[ \wfrac{x}{2} \]
\[ \wfrac{x+y}{2} \]
\[ \wfrac{\sum_{i=1}^{N} i^3}{x+y+z+t} \]
\[ \wfrac{\sum_{i=1}^{N} i^3}{\sum_{i=1}^{N} i} \]

\setmax{34pt}{10pt} % Manual maximum size

\[ \wfrac{\sum_{i=1}^{N} i^3}{\sum_{i=1}^{N} i} \]

\setmaxeq{x} % Reference equation again

\[ \wfrac{x}{x} \]
\[ \efrac{x}{x} \]
\end{document}

And it looks like this:

result

Options:

  • text: compare to the equation in \textstyle.
  • display: compare to the equation in \displaystyle.
  • none: compare to the equation in whatever style is currently active.
  • noparen: no parentheses
  • small: small maximum height and width
  • big: big maximum height and width
  • huge: huge maximum height and width
  • lparen: set left paren, eg: lparen=\left[
  • rparen: set right paren, eg: rparen={\right]}
  • div: set division mark, eg: div=\div

Commands

  1. \wfrac: fraction following 'less' rules.
  2. \efrac: fraction following 'less or equal' rules.
  3. \setmax: set the maximum size.
  4. \setmaxeq: set the maximum size using a reference equation.
  5. \getmax: get the maximum size.
  6. \getsize: get the size from an equation.
  7. \setparen: set the parentheses, takes two arguments.
  8. \setdiv: set the division mark.

And here is wfrac.sty:

\NeedsTeXFormat{LaTeX2e}[1994/12/01]
\ProvidesPackage{wfrac}[2012/11/03 v1.01 intelligent fractions]

% Lengths and widths
\newdimen \wfrac@hx
\newdimen \wfrac@hy
\newdimen \wfrac@hmax
\newdimen \wfrac@wx
\newdimen \wfrac@wy
\newdimen \wfrac@wmax
\newdimen \wfrac@wmaxcalc

% Parenthesis and division mark
\newcommand*{\wfrac@lparen}{\left(}
\newcommand*{\wfrac@rparen}{\right)}
\newcommand*{\wfrac@div}{\middle/}

% Options
\IfFileExists{xkeyval.sty}{
    \RequirePackage{xkeyval}
    \DeclareOptionX{lparen}{\renewcommand*{\wfrac@lparen}{##1}}
    \DeclareOptionX{rparen}{\renewcommand*{\wfrac@rparen}{##1}}
    \DeclareOptionX{div}{\renewcommand*{\wfrac@div}{##1}}
}{
    \let\DeclareOptionX\DeclareOption
    \let\ExecuteOptionsX\ExecuteOptions
    \let\ProcessOptionsX\ProcessOptions
}

\DeclareOptionX{text}{\edef\wfrac@style{\textstyle}}
\DeclareOptionX{display}{\edef\wfrac@style{\displaystyle}}
\DeclareOptionX{none}{\edef\wfrac@style{}}
\DeclareOptionX{noparen}{\renewcommand*{\wfrac@lparen}{}\renewcommand*{\wfrac@rparen}{}}
\DeclareOptionX{small}{\wfrac@wmax = 25pt \wfrac@hmax = 10pt}
\DeclareOptionX{big}{\wfrac@wmax = 50pt \wfrac@hmax = 50pt}
\DeclareOptionX{huge}{\wfrac@wmax = 100pt \wfrac@hmax = 100pt}
\ExecuteOptionsX{text,small}
\ProcessOptionsX\relax

% Fraction variations
\newcommand*{\wfrac@Afrac}[2]{\left. \wfrac@lparen #1 \wfrac@rparen \wfrac@div \wfrac@lparen #2 \wfrac@rparen \right.}
\newcommand*{\wfrac@Bfrac}[2]{\frac{1}{#2}\wfrac@lparen #1 \wfrac@rparen}
\newcommand*{\wfrac@Cfrac}[2]{\frac{#1}{#2}}

% Main commands
\newcommand*\setparen[2]{
    \renewcommand*{\wfrac@lparen}{#1}
    \renewcommand*{\wfrac@rparen}{#2}
}

\newcommand*\setdiv[1]{
    \renewcommand*{\wfrac@div}{#1}
}

\newcommand*\setmax[2]{
    \wfrac@wmax = #1
    \wfrac@hmax = #2
}

\newcommand*\setmaxeq[1]{
    \settowidth{\wfrac@wmax}{$ \wfrac@style #1 $}
    \settoheight{\wfrac@hmax}{$ \wfrac@style #1 $}
}

\newcommand*\getmax{
    \the\wfrac@wmax $\times$ \the\wfrac@hmax
}

\newcommand*\getsize[1]{
    \settowidth{\wfrac@wx}{$ \wfrac@style #1 $}
    \settoheight{\wfrac@hx}{$ \wfrac@style #1 $}
    \the\wfrac@wx $\times$ \the\wfrac@hx
}

\newcommand*\wfrac[2]{
    \settowidth{\wfrac@wx}{$ \wfrac@style #1 $}
    \settowidth{\wfrac@wy}{$ \wfrac@style #2 $}
    \settoheight{\wfrac@hx}{$ \wfrac@style #1 $}
    \settoheight{\wfrac@hy}{$ \wfrac@style #2 $}    
    % max(w0, 2 * wy)
    \ifdim \wfrac@wmax < 2\wfrac@wy
        \wfrac@wmaxcalc = 2\wfrac@wy
    \else
        \wfrac@wmaxcalc = \wfrac@wmax
    \fi
    %
    \ifdim \wfrac@hy < \wfrac@hmax
        \ifdim \wfrac@wy < \wfrac@wmax
            \ifdim \wfrac@hx < \wfrac@hmax
                \ifdim \wfrac@wx < \wfrac@wmaxcalc
                    \let\wfrac@frac=\wfrac@Cfrac
                \else
                    \let\wfrac@frac=\wfrac@Bfrac
                \fi
            \else
                \let\wfrac@frac=\wfrac@Bfrac
            \fi 
        \else
            \let\wfrac@frac=\wfrac@Afrac
        \fi
    \else
        \let\wfrac@frac=\wfrac@Afrac
    \fi
    %
    \wfrac@frac{#1}{#2}
}

\newcommand*\efrac[2]{
    \settowidth{\wfrac@wx}{$ \wfrac@style #1 $}
    \settowidth{\wfrac@wy}{$ \wfrac@style #2 $}
    \settoheight{\wfrac@hx}{$ \wfrac@style #1 $}
    \settoheight{\wfrac@hy}{$ \wfrac@style #2 $}    
    % max(w0, 2 * wy)
    \ifdim \wfrac@wmax < 2\wfrac@wy
        \wfrac@wmaxcalc = 2\wfrac@wy
    \else
        \wfrac@wmaxcalc = \wfrac@wmax
    \fi
    %
    \ifdim \wfrac@hy > \wfrac@hmax
        \let\wfrac@frac=\wfrac@Afrac
    \else
        \ifdim \wfrac@wy > \wfrac@wmax
            \let\wfrac@frac=\wfrac@Afrac
        \else
            \ifdim \wfrac@hx > \wfrac@hmax
                \let\wfrac@frac=\wfrac@Bfrac
            \else
                \ifdim \wfrac@wx > \wfrac@wmaxcalc
                    \let\wfrac@frac=\wfrac@Bfrac
                \else
                    \let\wfrac@frac=\wfrac@Cfrac
                \fi
            \fi 
        \fi
    \fi
    %
    \wfrac@frac{#1}{#2}
}

\endinput
3
  • Nice! It might be better to define \newcommand*{\wfrac@Afrac}[2]{\left.\left(#1\right)\middle/\left(#2\right)\right.}, \newcommand*{\wfrac@Bfrac}[2]{\frac{1}{#2}\left(#1\right), and \newcommand*{\wfrac@Cfrac}[2]{\frac{#1}{#2}}, and in the nested conditionals use \let\wfrac@frac=\wfrac@Afrac (or Bfrac, Cfrac...), and outside the conditionals call \wfrac@frac{#1}{#2}. This is a bit safer to allow for arbitrary arguments #1 and #2. Also, it would be nice to provide a variant which does not add parentheses in the A and B forms, but I am not sure what syntax is best. Nov 3, 2012 at 11:35
  • Great suggestions! I've added a new version of wfrac.sty. It includes the \setparen{...}{...} and \setdiv{...} commands to change the parentheses and division mark. I've also added options: text, display, none, noparen, small, big, huge, lparen, rparen and div.
    – Silke
    Nov 3, 2012 at 12:36
  • It would be even nicer to control the presence of absence of parentheses for the numerator and denominator of each fraction independently: I am thinking of the case where a numerator or denominator is a single object. For instance, \wfrac[paren = num]{x+y}{e^{i\pi xyz}} could give (x+y)/e^{i\pi xyz}. The values of the paren option would be num, denom, none, both or variants of that. That is actually not enough for cases like \wfrac{\sum_j x_j}{y}, for which correct forms are \frac{#1}{#2}, (#1)/#2, and \frac{1}{#2}#1, with parentheses or not around #1. Nov 3, 2012 at 17:09

You must log in to answer this question.

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