为什么 \the 不能被扩展?

为什么 \the 不能被扩展?
\documentclass{article}
\begin{document}
\tracingmacros=2
\newlength{\len} \setlength{\len}{1cm}  we want to write out \verb$\len$ in cm

\the\len { oops, answer in pt}

\setlength{\len}{0.0352\len}
\the\len { good, now we just need to replace pt with cm}

\def\num#1pt{#1cm}
\num1pt { so far so good}

\def\temp{1pt}
\num\temp { not so hot} 0pt %0pt added to end of line just to prevent error message

\expandafter\num\temp   { that works}

\expandafter\num\the\len { but not that} 0pt

\edef\temp{\the\len}
\expandafter\num\temp { okay I'm stuck} 0pt

\makeatletter
\strip@pt\len cm Thank you, that works great!
\makeatother

\end{document}

该文件就是问题所在。

如果你想知道我想要这个做什么,请查看\whereami查看 http://www.elfsoft2000.com/projects/speaker.pdf

答案1

答案是艾利特解释如何得到你想要的东西,但也值得了解这种方法有什么问题

\def\num#1pt{#1cm}

首先要注意的是\the 可扩展,您可以在内部确认\edef

\newdimen\mydimen
\edef\demo{\the\mydimen}
\show\demo

给出

> \demo=macro:
->0.0pt.

但这里重要的是,pt这由两个“其他”(类别代码 12)字符组成,而不是两个“字母”。因此,要去掉字母,我们需要使用正确的类别代码pt。LaTeX 内核定义了\rem@pt使用

\begingroup
  \catcode`P=12
  \catcode`T=12
  \lowercase{
    \def\x{\def\rem@pt##1.##2PT{##1\ifnum##2>\z@.##2\fi}}}
  \expandafter\endgroup\x

这个想法是将PT变成“其他”字符,并用于创建小写的“其他”pt。可以使用 e-TeX 设置更清晰的定义:

\makeatletter
\edef\@tempa{%
  \def\noexpand\rem@pt##1\detokenize{pt}{##1}%
}
\@tempa

我使用 将其\detokenize转换pt“其他”字符,但不包含小写字母。

LaTeX 提供了\strip@pt包装器\rem@pt,然后可以按照 A.Ellett 所演示的那样使用。

答案2

pt这个答案涉及到的转换的精度cm

包裹printlen

该包使用简单的 TeX 算术,在 dimen 寄存器前面printlen使用一个因子。0.0351459

e-TeX 的\dimexpr

e-TeX 的 更精确\dimexpr,因为如果乘法后跟除法,它使用 64 位乘积作为中间值。结果四舍五入为 1/65536,因为 TeX 中的最小单位是1sp

包裹fp

包提供了定点运算fp。它支持从 -999999999999999999999.999999999999999999 到 +9999999999999999999999.9999999999999999999999。这是最精确的方法。句点后面的数字可以减少,因为 TeX 最小单位是1sp。因此超过七位数字没有多大意义。

其他套餐

  • LaTeX3 有一个用于定点运算的模块。
  • pgf/TikZ带有几种方法:
    • \pgfmathparse,...
    • 定点运算库
    • 浮点单元库

比较

\documentclass{article}
\usepackage[hmargin=1pt]{geometry}

\makeatletter

\usepackage{printlen}
\newcommand*{\PTtoCMprintlen}[1]{%
  \begingroup
    \uselengthunit{cm}%
    \dimen@=#1\relax
    \printlength{\dimen@}%
  \endgroup
}

\newcommand*{\PTtoCMdimexpr}[1]{%
  \strip@pt\dimexpr(#1)*254/7227\relax cm%
}

\usepackage{fp}
\newcommand*{\PTtoCMfp}[1]{%
  \begingroup
    \dimen@=#1\relax
    \FPset{\PTtoCM@tmp}{\number\dimen@}%
    \FPmul{\PTtoCM@tmp}{\PTtoCM@tmp}{2.54}%
    \FPdiv{\PTtoCM@tmp}{\PTtoCM@tmp}{4736286.72}% 72.27 * 65536
    \FPprint{\PTtoCM@tmp}%
    cm%
  \endgroup
}

\newcommand*{\PTtoCMfpround}[1]{%
  \begingroup
    \dimen@=#1\relax
    \FPset{\PTtoCM@tmp}{\number\dimen@}%
    \FPmul{\PTtoCM@tmp}{\PTtoCM@tmp}{2.54}%
    \FPdiv{\PTtoCM@tmp}{\PTtoCM@tmp}{4736286.72}% 72.27 * 65536
    \FPround{\PTtoCM@tmp}{\PTtoCM@tmp}{7}%
    \FPprint{\PTtoCM@tmp}%
    cm%
  \endgroup
}

\makeatother

\begin{document}
\newcommand*{\test}[1]{%
  #1 & \PTtoCMprintlen{#1} & \PTtoCMdimexpr{#1}
     & \PTtoCMfp{#1} & \PTtoCMfpround{#1} \\%  
}
\begin{tabular}{lllll}
  & printlen & dimexpr & fp & fpround \\
  \hline
  \test{1cm}
  \test{\the\maxdimen}
  \test{89.3999pt}
  \test{1sp}
\end{tabular}
\end{document}

结果

评论:

  • 如果1cm分配给长度,则会四舍五入到单位sp,因此“精确”的结果不是1cm,因此包的结果fp更正确。

  • TeX 在其长度或 e-TeX 的情况下打印的最大位数\dimexpr针对最小单位进行了优化1sp。将数字从转换pt为较大单位后cm,数字变得太小而无法打印,结果四舍五入为零。

答案3

如果你尝试将存储在中的 LaTeX 内部长度转换pt为更人类可读格式,那么你可以尝试类似以下操作:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\makeatletter
\newcommand{\pttocm}[1]{\texttt{\string#1}=\the#1 is approximately \strip@pt\dimexpr0.03514598#1\relax cm}
\makeatother

\begin{document}

\newlength{\triallen}
\setlength{\triallen}{89.3999pt}

\pttocm{\triallen}

\end{document}

在此处输入图片描述

或者,正如 @werner 指出的那样,您可以使用该包printlen,然后

\uselengthunit{cm}
\printlength{\triallen}

关于丢失的空间在您的代码中:这是因为裸的 LaTeX 宏(即后面没有括号的宏)吞噬了下面的空间。

答案4

可以使用lengthconvert包或直接使用 LaTeX3 函数;第一种方式更具可定制性。

\documentclass{article}
\usepackage{lengthconvert}
\newlength{\len}

\begin{document}
\setlength{\len}{1cm}
\Convert[unit=cm]{\len}

\addtolength{\len}{2.5cm}
\Convert[unit=cm]{\len}

\Convert[unit=cm]{1in}

\Convert[unit=pt,precision=2]{1in}

\ExplSyntaxOn
\dim_to_unit:nn {1in}{1mm}
\ExplSyntaxOff
\end{document}

在此处输入图片描述

相关内容