深度和高度混淆

深度和高度混淆

我创建了两个等式:

  1. $x \notin \mathbb{N}$; 和
  2. $x \in \mathbb{N}$

事实证明,两者具有相同的深度值:

  1. 深度 = 0.39098pt
    高度 = 7.5pt

  2. 深度 = 0.39098pt
    高度 = 6.88889pt

显然,第一个方程的深度应该比第二个方程更大,因为符号\notin更深。

怎么会这样?

这是用于生成两者的代码:

\documentclass[10pt]{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[usenames]{color}


\pagestyle{empty}
\newsavebox{\eqbox}
\newlength{\width}
\newlength{\height}
\newlength{\depth}

\begin{lrbox}{\eqbox}
{$ x \notin \mathbb{N} $}
\end{lrbox}

\settowidth {\width}  {\usebox{\eqbox}}
\settoheight{\height} {\usebox{\eqbox}}
\settodepth {\depth}  {\usebox{\eqbox}}
\newwrite\file
\immediate\openout\file=\jobname.bsl
\immediate\write\file{Depth = \the\depth}
\immediate\write\file{Height = \the\height}
\addtolength{\height} {\depth}
\immediate\write\file{TotalHeight = \the\height}
\immediate\write\file{Width = \the\width}
\closeout\file
\begin{document}
\usebox{\eqbox}
\end{document}

谁能告诉我这是为什么?

答案1

并非总是如此。最好的观察方式是从边界框的角度来看待这个问题:

在此处输入图片描述

\documentclass[10pt]{article}
\usepackage{amssymb,xcolor}% http://ctan.org/pkg/{amslatex,xcolor}
\newcommand{\showbb}[1]{{\color{red!50}\leavevmode\rlap{\fbox{\phantom{#1}}}}#1}
\begin{document}

\setlength{\fboxsep}{-\fboxrule}
\showbb{$ x \notin \mathbb{N} $} \quad
\showbb{$ x \in \mathbb{N} $}
\end{document}

如上所述,很明显两者具有相同的深度,但高度不同。为什么?这是由字体设计师在每个符号的字体规范中决定的。在某些情况下,字符/符号的边界框取决于其后的内容(例如,V后跟A)。在这种情况下(或最有可能),符号的深度被设置为不会影响基线跳过。

检查这一点的一种方法是,如果要\notin在两行连续的线条上有两个符号。如果符号的深度更大,线条分离会使输出看起来很尴尬……仅在一个位置。为了避免这种情况,并且知道符号\not的“ ”部分是一条(细)规则,如果它向下延伸得比预期的要远,它不应该影响读者。

答案2

这是 实施的副作用\notin。来自fontmath.ltx(重新格式化):

\DeclareRobustCommand\notin{%
  \mathrel{%
    \m@th
    \mathpalette\c@ncel\in
  }%
}
\def\c@ncel#1#2{%
  % #1: math style
  % #2: the symbol (here: \in)
  \m@th
  \ooalign{%
    $\hfil#1\mkern1mu/\hfil$%
    \crcr
    $#1#2$%
  }%
}

简化版\notin会制作一个只有一列的特殊表格。第一行包含一个水平居中、向右/移动的1mu。第二行包含符号 。但是,您看不到两条线。的诀窍\ooalign是将 设置\baselineskip为零。因此,两行共享相同的基线。整体放入一个垂直框(\vtop)。整个框的高度来自第一个框、第一条线、斜线的高度。现在第二个框、第二条线紧随其后,这意味着第一条线的深度不再计算。第二条线的高度也被忽略,但第二条线中符号的深度成为整个框的深度。

以下示例比较了不同的变体:

  • 前两个框包含单个字形,表明字符边界框是正确的。
  • 第三个框\notin显示了具有如上所述的原始定义的组合符号。
  • 第四个框\NotIn使用重写的\c@ncel宏(\NewC@ncel),同时考虑了高度和深度。
  • 为了进行比较,最后一个框使用不同的符号\not和方法来表示否定。
\documentclass{article}

\usepackage{xcolor}

\makeatletter
\newcommand*{\NotIn}{%
  \mathrel{%
    \mathpalette\NewC@ncel\in
  }%
}
\newcommand*{\NewC@ncel}[2]{%
  % #1: math style
  % #2: symbol
  \sbox0{$#1#2\m@th$}%
  \sbox2{$#1\mkern1mu/\m@th$}%
  \ifdim\wd2>\wd0 %
    \wd0=\wd2 %
  \else
    \setbox2=\hbox to \wd0{\hfil\unhcopy2\hfil}%
  \fi
  \rlap{\copy2}%
  \copy0 %
}
\makeatother

\newcommand*{\test}[1]{%
  \begingroup
    \setlength{\fboxsep}{0pt}%
    \setlength{\fboxrule}{.2pt}%
    \sbox0{$#1$}%
    \typeout{* [\detokenize{#1}: height=\the\ht0, depth=\the\dp0}%
    \fcolorbox{blue}{white}{\copy0 } \texttt{\detokenize{#1}}%
    \par
  \endgroup
}

\begin{document}
  \test{\in}
  \test{/}
  \test{\notin}
  \test{\NotIn}
  \test{\not\in}
\end{document}

结果

如果要使用(而不是像示例中那样使用\notin新的宏),那么可以重新定义:\NotIn\c@ncel

\makeatletter
\newcommand*{\NewC@cncel}{...}% see above
\let\c@ncel\NewC@ncel
\makeatother

修复了以下建议\ooalign

以下测试文件可用于纯 TeX 和 LaTeX,它重新定义了\ooalign。首先将单元格内容放入一个框中以测量其高度和深度,然后将整个框设置为最大高度和深度。

\ifx\documentclass\undefined
  \nopagenumbers
  \catcode`\@=11 %
\else
  \documentclass{article}
  \pagestyle{empty}
  \begin{document}
  \makeatletter
\fi

\let\plain@ooalign\ooalign

%%% begin: \ooalign %%%
\newdimen\ooalign@height
\newdimen\ooalign@depth
% The implementation merges the original `\ooalign'
% with the modified contents of `\oalign'.
% The heights and depths are measured and the overall box
% is adjusted to get the maximum height and depth.
\def\ooalign#1{%
  \leavevmode
  \begingroup
    \setbox\z@\vtop{%
      \baselineskip\z@skip
      \lineskip\z@ % might not be needed
      \lineskiplimit=-\maxdimen
      \global\ooalign@height\z@
      \global\ooalign@depth\z@
      \ialign{%
        % the cell contents is measured and
        % the maximum values for height and depth are remembered
        \setbox\z@\hbox{##}%
        \ifdim\ht\z@>\ooalign@height
          \global\ooalign@height\ht\z@
        \fi
        \ifdim\dp\z@>\ooalign@depth
          \global\ooalign@depth\dp\z@
        \fi
        \unhcopy\z@
        \crcr
        #1%
        \crcr
      }%
    }%
    \vtop{%
      % update the height if needed
      \ifdim\ooalign@height>\ht\z@
        \hrule width\z@ height \ooalign@height depth\z@
        \kern-\ht\z@
      \fi
      \unvcopy\z@
      % update the depth if needed
      \ifdim\ooalign@depth>\dp\z@
        \kern-\dp\z@
        \kern\ooalign@depth
      \fi
    }%   
  \endgroup
}
%%% end: \ooalign %%%

% for testing

\ifx\fbox\undefined
  \newdimen\fboxrule
  \newdimen\fboxsep 
  \newbox\@tempboxa 
  \newdimen\@tempdima

  \long\def\fbox#1{%
    \leavevmode
    \setbox\@tempboxa\hbox{%
      \begingroup
        \kern\fboxsep{#1}\kern\fboxsep
      \endgroup}%
    \@frameb@x\relax
  }%
  \def\@frameb@x#1{%
    \@tempdima\fboxrule
    \advance\@tempdima\fboxsep
    \advance\@tempdima\dp\@tempboxa
    \hbox{%
      \lower\@tempdima\hbox{%
        \vbox{%
          \hrule height\fboxrule
          \hbox{%
            \vrule width\fboxrule
            #1%
            \vbox{%
              \vskip\fboxsep
              \box\@tempboxa
              \vskip\fboxsep}%
            #1%
            \vrule width\fboxrule}%
          \hrule height\fboxrule   
        }%
      }%  
    }%    
  }%      
\fi       
\fboxsep=0pt
\fboxrule=.1pt

\def\test{a\fbox{$\notin$}b\fbox{\copyright}c}

% original \ooalign
\begingroup
  \let\ooalign\plain@ooalign
  \test
\endgroup

% new \ooalign
\test

\ifx\enddocument\undefined
  \def\next{\end}%
\else
  \def\next{\end{document}}%
\fi
\next

结果

答案3

\notin定义为纯 tex,并带入乳胶中。它不需要乳胶或amsfonts证明缺乏深度。

相关元素是在(via )\ooalign的定义中的使用。 定义如下(texbook,第 356 页):\notin\c@ancel\ooalign

\def\ooalign{\lineskiplimit-\maxdimen \oalign} % chars over each other

有效\lineskiplimit地抵消了组件的任何高度或深度,正如这个小纯 tex 脚本所示:

\setbox0=\hbox{$/$}
\setbox1=\hbox{\ooalign{.\crcr/\crcr}
\showthe\dp0
\showthe\dp1
\bye

输出(到屏幕)是这些值:

> 2.5pt.
l.7 \showthe\dp0
?     
> 0.0pt.
l.8 \showthe\dp1

\showthe\ht1还将报告的值0.0pt

这是否给任何人造成了问题仍是一个悬而未决的问题;然而,30 多年来它并没有给任何人带来足够的困扰以致于将其报告为错误。

答案4

\dpnotin具有斜线深度的更简单的实现:

\documentclass{article}
\makeatletter
\DeclareRobustCommand{\dpnotin}{%
  \mathrel{\m@th\mathpalette\c@ncel{{\in}\vphantom{/}}}%
}
\makeatother

\begin{document}
\fboxsep=0pt
\fbox{$x\notin N$}\,\fbox{$x\dpnotin N$}

\fbox{$x\notin N$}\,\fbox{$x\notin N$}
\end{document}

我们传递\c@ncel参数{\in}\vphantom{/},因此幻像将以正确的方式设置构造的深度。示例中的第二行只是检查水平尺寸是否不变;第三行和第四行用于检查下标中的符号。

在此处输入图片描述

相关内容