我们都知道,不用括号也可以写出依赖于参数的幂。例如:x^2=x^{2}
。
当处理次数大于 9 的多项式时,我们现在可以不使用括号,例如x^10
。
\begingroup
\catcode`\^=\active
\gdef^#1#2{
\ensuremath{\sp{#1#2}}}
\endgroup
\mathcode`\^=\string"8000
\catcode`\^=12
适用于x^12
和任何其他 2 位指数。
我希望仅当后面跟着^
两位数字时才应用此规则。我希望这样做可以让代码更简洁、更易读。有什么想法吗?
答案1
首先,我要说的是,我认为这是一个非常糟糕的想法,我强烈建议你不要使用它。它更有可能让下一个阅读源代码的人(可能是你,稍后)感到困惑,而不是让它更具可读性。其次,我只是勉强测试了一下,它几乎肯定会以奇怪的方式崩溃。(第三——这可能很小——通过更改的类别代码^
,这会破坏使用插入字符的能力,^^
而无需先暂时将的类别代码^
(或其他标记)更改回 7。)
话虽如此,似乎上班。
\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
}{%
%
}%
}
\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}
它的工作原理是检查 之后的第一个字符是否^
具有与 相同的类别代码,0
然后检查 ASCII 值是否在 '0'–'9' 范围内。假设这两个条件都为真,它会对 之后的第二个字符执行相同的检查^
。如果所有条件都满足,它会生成(本质上) 。如果任何条件不满足,它会根据需要^{#1#2}
插入上标标记以及 之后的第一个和第二个标记。^
编辑:受到 Mico 的回答的启发,这里有一个简单的修改,它支持任意数量的数字以及前导-
。
\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
这是一个基于 LuaLaTeX 的解决方案。它适用于数字指数任意数量的数字,而不仅仅是 1 或 2 位数字。它还可以处理指数开头的可选符号(-
或)。+
如果您对代码的作用感到好奇:(a) 它设置了一个名为 的 Lua 函数fix_expo
,该函数扫描输入行并将所有^
后跟可能一些空格、后跟模式“可选-
或+
符号、后跟可能一些空格、后跟 1 个或多个数字”的替换为^{<pattern>}
。(b) LaTeX 宏\FixExpo
将 Lua 函数分配给 LuaTeX 的process_input_buffer
回调。此回调在非常早期的阶段运行,前TeX 开始其常规输入处理。
如果由于某种原因需要终止此功能的运行,只需发出指令即可\UnfixExpo
。要重新激活该功能,只需\FixExpo
再次运行即可。
直接添加一些开销代码来确保 Lua 函数fix_expo
能够不是在类似 的环境中操作verbatim
。(或者,如果您的文档不包含太多类似 verbatim 的环境,只需在这些环境之前和之后分别执行\UnfixExpo
和即可\FixExpo
。)
% !TeX program = lualatex
\documentclass{article}
%% Lua-side code:
\usepackage{luacode}
\begin{luacode}
function fix_expo( s )
return ( s:gsub ( "%^%s-([%-%+]?%s-%d+)", "^{%1}" ) )
end
\end{luacode}
% LaTeX-side code: Macros '\FixExpo' and '\UnfixExpo'
\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")}}
% Activate the Lua function by default:
\AtBeginDocument{\FixExpo}
\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}
答案3
这将允许未分组的数字在指数中分组,并且它们可能包含前导-
或+
。
\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}