如何在不将指数括在一对花括号中的情况下计算幂?

如何在不将指数括在一对花括号中的情况下计算幂?

我们都知道,不用括号也可以写出依赖于参数的幂。例如: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
    }{%
        &#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

它的工作原理是检查 之后的第一个字符是否^具有与 相同的类别代码,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

答案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}

在此处输入图片描述

相关内容