栈桥问题:如何避免输出中的 >=

栈桥问题:如何避免输出中的 >=

TeX 字符之间不留空格\mathrel,因此可以输入 := 来定义。但粗心的作者经常会输入类似

< a, b > = < c, d >  

表示两个标量积相等,并使中间三个字符粘在一起,等号周围没有空格。(我确实告诉他们使用\langleand \rangle,这很有用。)至少\mathrel在这种情况下,有没有巧妙的方法可以覆盖惯例,以便等号与其他符号分开,但仍然是数学关系字符?

答案1

诀窍是将文档中出现的所有<和的列表存储在 aux 文件内,并在第二次运行中使用它来决定什么应该是和,什么应该是和。><>\left\langle\right\rangle

解决方案有点长,抱歉。请参阅内联评论。

\makeatletter
% We could probably add some customization here.
% 
% < and > as a relation or as a delimiter
\mathchardef\lt@relation=\mathcode`\<
\mathchardef\ltgt@bar@relation=\mathcode`\|
\mathchardef\gt@relation=\mathcode`\>
% Note: \ltgtstep and \ltgtunstep are needed because of the 
% \left and \right. Also note that their placement (inside the group)
% is critical.
\def\lt@delimiter{\left\langle\ltgtstep}
\def\ltgt@bar@delimiter{\middle|}
\def\gt@delimiter{\ltgtunstep\right\rangle}
% < and > revert to the relation symbol if the .aux 
% disagrees with what we see in the current run.
\let\lt@error@relation\lt@relation
\let\ltgt@bar@error@relation\ltgt@bar@relation
\let\gt@error@relation\gt@relation
\let\lt@error@delimiter\lt@relation
\let\ltgt@bar@error@delimiter\ltgt@bar@relation
\let\gt@error@delimiter\gt@relation


% As in other solutions, we make < and > active in math mode.
% The corresponding control sequences have been defined above.
\begingroup
  \catcode`\<=\active
  \catcode`\|=\active
  \catcode`\>=\active
  \gdef<{\lt@active}
  \gdef|{\ltgt@bar@active}
  \gdef>{\gt@active}
\endgroup
\mathcode`\<="8000
\mathcode`\|="8000
\mathcode`\>="8000

% ===================

% The above commands will be called via 
%   \csname lt@\ltgt@error@\ltgt@type\endcsname
% where \ltgt@error@ is {} by default and can be {error@}, and
% where \ltgt@type is {relation} or {delimiter}.
\gdef\ltgt@error@{}
\def\ltgt@type{relation}


% \ltgt@list will hold our list of "<", ">", "|". Each time we append,
% we check that the symbol agrees with the corresponding one from the
% .aux file. If not, we fall back on the error mode.
\gdef\ltgt@list{}
\def\ltgt@append#1{%
  \xdef\ltgt@list{\ltgt@list#1}%
  \ltgt@prev@pop%
  \unless\ifx\ltgt@prev@head#1%
  \gdef\ltgt@error@{error@}%
  \fi%
}
% We pop the list from the .aux file as we construct the new list.
\def\ltgt@prev@pop{\expandafter\ltgt@prev@pop@aux\ltgtprevlist\relax\relax}
\def\ltgt@prev@pop@aux#1#2\relax{%
  \xdef\ltgtprevlist{#2}%
  \ifx#1\relax%
  \global\let\ltgt@prev@head\relax%
  \else%
  \global\let\ltgt@prev@head#1%
  \fi}

% To take care of grouping
\def\ltgt@append@open{%
  \loop
  \ifnum\ltgt@depth<\currentgrouplevel
  \ltgt@append{(}%
  \global\advance \ltgt@depth by 1\relax
  \def\ltgt@type{relation}%
  \repeat
}
\def\ltgt@append@close{%
  \loop
  \ifnum\ltgt@depth>\currentgrouplevel
  \ltgt@append{)}%
  \global\advance \ltgt@depth by -1\relax
  \aftergroup\ltgt@append@close
  \repeat}


% We will later \let<\lt@active and \let>\gt@active. For now, we just
% define these commands. Each has two pieces: first fill the \ltgt@list,
% putting many "|" to ensure that different groups are really separated
% by at least one "|". Second, typeset the correct symbol depending on
% what can be read from the prevlist (extracted from the .aux file).
\newcount\ltgt@depth
\def\ltgtstep{\global\advance\ltgt@depth by 1\relax}
\def\ltgtunstep{\global\advance\ltgt@depth by -1\relax}
\def\ltgt@openclose{%
  \aftergroup\ltgt@append@close%
  \unless\ifnum\ltgt@depth=\currentgrouplevel%
  %\global\ltgt@depth\currentgrouplevel%
  \ltgt@append@open%
  \fi%
}
\def\lt@active{%
  % fill the list
  \ltgt@openclose%
  \ltgt@append{<}%
  % typeset
  \ltgt@ifnextgt@TF{\def\ltgt@type{delimiter}}{\def\ltgt@type{relation}}%
  \csname lt@\ltgt@error@\ltgt@type\endcsname%
}
\def\ltgt@bar@active{%
  % fill the list
  \ltgt@openclose%
  \ltgt@append{|}%
  % typeset
  \csname ltgt@bar@\ltgt@error@\ltgt@type\endcsname%
}
\def\gt@active{%
  % fill the list
  \ltgt@openclose%
  \ltgt@append{>}% 
  % typeset
  \csname gt@\ltgt@error@\ltgt@type\endcsname%
  \def\ltgt@type{relation}%
}


% When we see a <, we use \ltgt@ifnextgt@TF{.t.}{.f.} to test if the
% head of the prevlist is a >. If so, we execute {.t.}, otherwise {.f.}.
\newcount\ltgt@ifnextgt@count
\def\ltgt@ifnextgt@TF{%
  \global\ltgt@ifnextgt@count0\relax%
  \expandafter\ltgt@ifnextgt@readone\ltgtprevlist\relax\relax%
  \expandafter\ltgt@ifnextgt@aux\ltgtprevlist\relax%
}
\def\ltgt@ifnextgt@readone#1{%
  %\ltgt@ifnextgt@count
  %\@ltgt@ifnextgt@false%
  \ifx#1\relax
  \expandafter\ltgt@ifnextgt@throw@FT
  \fi
  \ifx#1(%
  \global\advance\ltgt@ifnextgt@count by 1\relax
  \fi
  \ifx#1)%
  \global\advance\ltgt@ifnextgt@count by -1\relax
  \fi
  \ifnum\ltgt@ifnextgt@count<0\relax % no ">" can be found.
  \expandafter\ltgt@ifnextgt@throw@FT
  \fi
  \ifnum\ltgt@ifnextgt@count=0\relax
    \ifx#1<\relax % the first relevant character is not ">"
    \expandafter\expandafter\expandafter\ltgt@ifnextgt@throw@FT
    \else
      \ifx#1>\relax % ">" was found!
      \expandafter\expandafter\expandafter\expandafter
      \expandafter\expandafter\expandafter\ltgt@ifnextgt@throw@TF
      \fi
    \fi
  \fi
  \ltgt@ifnextgt@readone
}
\def\ltgt@ifnextgt@throw@FT#1#{\ltgt@use@FT}
\def\ltgt@ifnextgt@throw@TF#1#{\ltgt@use@TF}


\def\ltgt@ifnextgt@aux#1#2#{% arg #2 delimited by brace, thrown away.
  \ifx#1>%
  \expandafter\ltgt@use@FTF%
  \else%
  \ifx#1|%
  \expandafter\expandafter\expandafter\ltgt@use@T%
  \else%
  % \ifx#1(%)
  % \expandafter\expandafter\expandafter\expandafter
  % \expandafter\expandafter\expandafter\
  \expandafter\expandafter\expandafter\ltgt@use@FFT%
  \fi%
  \fi%
  {\ltgt@ifnextgt@aux#2}%
}

\long\def\ltgt@use@T#1{#1}
\long\def\ltgt@use@TF#1#2{#1}
\long\def\ltgt@use@FT#1#2{#2}
\long\def\ltgt@use@FTF#1#2#3{#2}
\long\def\ltgt@use@FFT#1#2#3{#3}


% We put the definition of the relevant list in the .aux file at the end
% of the run. This file is read at \begin{document}.
\AtEndDocument{\write\@auxout{\gdef\noexpand\ltgtprevlist{\ltgt@list}}}
% 
% To ensure that \ltgtprevlist is defined in the first run, we do
\let\ltgtprevlist\relax



% Embedding the test example in the package itself (bad idea, but eh...)
\unless\ifx\documentclass\@twoclasseserror

\documentclass{article}
\begin{document}
The middle delimiter now works: $<a^2|x_{\sum_{i>j_1}i}>$, and nesting as well:
\[
<\frac{<u|v>+<v_1|v_2>}{<v_1|v>} v_1|v > = <u|v> + <v_1|v_2>,
\qquad {i<j}, {k>l}. % Note the use of braces to prevent seeing <j,k>. 
\]
How come the end didn't become $i<j, k>l$? because I enclosed each 
inequality in braces. Another case where this can be useful is to get
$<{<a,b>} a,b> = <a,b>^2$.

One more test:
\[
< {\sum |\lambda_i| v_i}| v > = 0
\]

\end{document}

\fi

答案2

有些作者确实想将<...>运算符与区分开来\langle...\rangle。在这种情况下,您可以通过以下方式获得正确的间距:

\newcommand*\diam [1] {\mathopen< #1 \mathclose>}
\newcommand*\scal [1] {\langle #1 \rangle}
% usage: \( \diam{\phi} = \diam{\psi} \neq \scal{\phi, \psi} \)

我很惊讶之前没人提到过这一点。

答案3

如果你可以让他们使用任何宏来实现这一点,那么

\newcommand*\sp[2]{\langle#1,#2\rangle}

可能是可行的方法。(好吧,也许不是,\sp因为那是\let^但可以指示标量积。)

由于您可能不希望在最终输出中出现小于或大于的情况,并且您的合著者不太可能会更改,因此您可能只需进行最后检查并修复他们的小错误。这就是我所做的。

答案4

更好的是,Lev Bishop 的回答在相关问题上,使用数学工具你可以定义:

\DeclarePairedDelimiter\ip{\langle}{\rangle}

然后将其\ip{a,b}用于内部产品。最棒的是,您还可以免费获得带星号的版本\ip*{a,b},它将根据需要自动调整分隔符的大小。

相关内容