6

We all know that it is possible to write a power, which depends on an argument, without using the braces. As an example: x^2=x^{2}.

When working with polynomials of degree greater than 9, we can now use no braces, such as x^10.

\begingroup
\catcode`\^=\active
\gdef^#1#2{
\ensuremath{\sp{#1#2}}}
\endgroup
\mathcode`\^=\string"8000
\catcode`\^=12

Works for x^12 and any other 2-digit exponent.

I would like to apply this rule only when what follows ^ are two digits. I'd like to do this to keep the code cleaner and readable. Any idea?

  • 8
    It sound like something that does the opposite of what you want. The code will not be cleaner or more readable by introducing some complicated code just to avoid braces. – hpekristiansen Jun 7 '17 at 3:46
  • 5
    Have fun catching all the corner cases... – Henri Menke Jun 7 '17 at 4:58
  • This is no sophisticated idea -- I am still looking into my older documents in order to replace even one-digit power statements by ^{2} etc. – user31729 Jun 7 '17 at 7:37
  • 4
    It does not make the code cleaner or more readable it makes it very fragile and hard to read! and means that fragments of your document will fail if copied into any other tex document. It is possible to do this but I would strongly advise against it. Why just digits for example x^n is x^{n}` but what do you want x^max to be, or x^my^n ? – David Carlisle Jun 7 '17 at 7:52
9

First, let me say that I think this is a pretty bad idea and I strongly recommend you don't use this. It's more likely to confuse the next person to read the source (possibly you, later) than it is to make it more readable. Second, I only barely tested this and it's almost certain to break in strange ways. (Third—and this is probably pretty minor—by changing the category code of ^, this breaks the ability to insert characters using ^^ without temporally changing the category code of ^ (or some other token) back to 7 first.)

That said, this seems to work.

\documentclass{article}

\makeatletter
\def\ifdigit#1{%
    \if#1\romannumeral0#1\relax
        \expandafter\@secondoftwo
    \else
        \expandafter\@firstoftwo
    \fi
}

\begingroup
\catcode`\&=7
\global\catcode`\^=\active
\gdef^{%
    \futurelet\exp@i\exponent@i
}
\gdef\exponent@i{%
    \ifcat0\exp@i
        \expandafter\exponent@ii
    \else
        \expandafter&%
    \fi
}
\gdef\exponent@ii#1{%
    \ifdigit{#1}{%
        \futurelet\exp@ii\exponent@iii
    }{%
        &#1%
    }%
}
\gdef\exponent@iii{%
    \ifcat0\exp@ii
        \expandafter\exponent@iv
    \else
        \expandafter&\expandafter\exp@i
    \fi
}
\gdef\exponent@iv#1{%
    \ifdigit{#1}{%
        &{\exp@i\exp@ii}%
    }{%
        &\exp@i\exp@ii
    }%
}
\endgroup
\mathcode`\^="8000
\makeatother

\begin{document}
$2^0+2^1+\cdots+2^31=2^32-1\ne2^{387}$
\end{document}

1

It works by checking that the first character after the ^ has the same category code as 0 and then that the ASCII value is in the range '0'–'9'. Assuming both of those are true, it performs the same check on the second character after the ^. If all conditions are satisfied, it produces (essentially) ^{#1#2}. If any condition is not satisfied, it inserts a superscript token and the first and second tokens following the ^ as needed.

Edit: Inspired by Mico's answer, here's a simple modification that supports any number of digits as well as a leading -.

\documentclass{article}

\makeatletter
\def\ifdigit#1{%
    \if#1\romannumeral0#1\relax
        \expandafter\@secondoftwo
    \else
        \expandafter\@firstoftwo
    \fi
}

\begingroup
\catcode`\&=7
\global\catcode`\^=\active
\gdef^{%
    \futurelet\exp@token\exponent@i
}
\gdef\exponent@i{%
    &\ifcat0\exp@token
        \bgroup\expandafter\exponent@ii
    \fi
}
\gdef\exponent@ii#1{%
    #1%
    \if-#1\expandafter\@firstoftwo
    \else\expandafter\@secondoftwo
    \fi
        {\futurelet\exp@token\exponent@iii}%
        {\ifdigit{#1}{\futurelet\exp@token\exponent@iii}{\egroup}}%
}
\gdef\exponent@iii#1{%
    \ifdigit{#1}%
        {#1\futurelet\exp@token\exponent@iii}%
        {\egroup#1}%
}
\endgroup
\mathcode`\^="8000
\makeatother

\begin{document}
$2^0+2^1+\cdots+2^31=2^32-1\ne2^387$

$x^-100+x^-10+x^-1+x^0+x^1+x^10+x^100$

$x^{2+5}$

$g^--g^+$
\end{document}

2

  • 1
    I would use another \ifnumber (should be called \ifdigit though because it only works for single tokens) \def\ifnumber#1{\if#1\romannumeral0#1\relax\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi} – Henri Menke Jun 7 '17 at 5:15
  • 1
    Blushing furiously at the thought I (ot at least my answer...) might have inspired you. :-) – Mico Jun 7 '17 at 10:00
6

Here's a LuaLaTeX-based solution, which works with numeric exponents with any number of digits, not just two. It can also handle the presence of an optional sign symbol (- or +) at the start of the exponent.

enter image description here

In case you're curious about what the code does: It (a) sets up a Lua function, called fix_expo, which scans lines of input and replaces all instances of ^ followed by (possibly some whitespace, followed by) the pattern "optional - or + symbol, followed by 1 or more digits" with ^{<pattern>} and (b) assigns this Lua function to the process_input_buffer callback. This callback operates at a very early stage, before TeX starts its regular input processing.

Should you need to terminate operation of this function, simply issue the directive \UnfixExpo. To reactivate the function, simply run \FixExpo again.

It would be easy to add some overhead code that ensures that the Lua function fix_expo does not operate inside verbatim-like environments. (Or, if your document doesn't contain too many verbatim-like environments, simply execute \UnfixExpo and \FixExpo, respectively, before and after such environments.)

% !TeX program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode}
\begin{luacode}
function fix_expo( s )
   return s:gsub ( "%^%s-([%-%+]?%s-%d+)(%D?)", "^{%1}%2" )
end
\end{luacode}

% TeX-side code
\newcommand\FixExpo{\directlua{
  luatexbase.add_to_callback ( "process_input_buffer" , fix_expo , "fix_expo")}}
\newcommand\UnfixExpo{\directlua{
  luatexbase.remove_from_callback ( "process_input_buffer" , "fix_expo")}}
\AtBeginDocument{\FixExpo} % activate the Lua function by default

\begin{document}
$2^0+2^1+\dots+2 ^ 31=2 ^ 32-1 \ne 2^ 387 $

$x ^ 5555 - y ^ 6666
=z^77777$

$x^-100+x^-10+x^-1+x^0+x^+1+x^+10+x ^ + 100$
\end{document}
2

This will allow ungrouped digits to be grouped in the exponent, and they may contain a leading - or +.

\documentclass{article}
\makeatletter
\let\svcarat^
\let\svsvcarat\svcarat
\catcode`^=\active %
\def^{\def\myexp{}%
  \def\firsttime{T}%
  \@ifnextchar\bgroup{\svcarat}{\findend}}
\def\findend#1{%
  \setbox0=\hbox{\ifcat0#1\gdef\digittest{T}\else\gdef\digittest{F}\fi}%
  \if T\digittest%
    \ifnum`#1<48\relax\def\digittest{F}\else\ifnum`#1>57\relax\def\digittest{F}\fi\fi%
  \fi%
  \if T\firsttime
    \ifx-#1\def\digittest{T}\else\ifx+#1\def\digittest{T}\fi\fi%
  \fi%
  \if T\digittest%
    \if T\firsttime\g@addto@macro\myexp{\bgroup}\fi%
    \g@addto@macro\myexp{#1}\def\next{\findend}%
  \else%
    \if\relax\myexp\relax%
      \let\svcarat\relax%
      \gdef\next{\let\svcarat\svsvcarat\svsvcarat#1}%
    \else%
      \gdef\next{#1}%
    \fi%
    \if T\firsttime\else\g@addto@macro\myexp{\egroup}\fi%
    \expandafter\svcarat\myexp%
  \fi%
  \def\firsttime{F}%
  \next}
\makeatother
\begin{document}
$x^a + x^ay + x^2 + x^2y + x^123y + x^\alpha y + x^{a23}y$\par
$x^{\mathit{1}23}y + x^\mathit{1}23$\par
$2^0+2^1+\cdots+2^31=2^32-1\ne2^387$\par
$x^-100+ x^-10+x^-1+x^0+x^+1+x^+10+x^+100$\par
$x^{2+5}$\par
$g^--g^+$
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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