如何打印命令的结果?

如何打印命令的结果?

错误代码:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

\begin{document}
\FPset\x{2}
\FPset\y{3}
\numprint{\ratio}
\end{document}

LaTeX 抱怨:

! 未定义控制序列。\next ->\@nil

l.14 \numprint{\ratio}

我如何评估\ratio并打印它\numprint

答案1

\numprint需要输入一串字符,而不是生成它的指令。对于fp,这些指令涉及赋值,而\numprint只能处理仅扩展为正确格式的数字的控制序列。因此必须提前生成字符串。(感谢 jfbu 注意到宏可以在 的参数中使用\numprint,只要它们扩展为具有正确格式的字符串即可。)

我建议您定义一个新命令,将 FP 表达式作为参数,可能是一个宏:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\numprintexpr}[2][\result]{%
  #2\relax\numprint{#1}}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
}

\begin{document}

\FPset\x{2}
\FPset\y{3}
\numprintexpr{\ratio}

\numprintexpr[\foo]{%
  \FPset\x{24}%
  \FPset\y{19}%
  \FPdiv\foo{\x}{\y}%
  \FPround\foo\foo{2}
}

\end{document}

可选参数(默认\result)告诉\numprintexpr哪个控制序列存储最终结果。

在此处输入图片描述


使用定点设施的不同实现expl3

\documentclass{article}
\usepackage{xparse}
\usepackage{numprint}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\fpeval}{m}
 {
  \fp_eval:n { #1 }
 }
\NewDocumentCommand{\fpset}{mm}
 {
  \fp_zero_new:N #1
  \fp_set:Nn #1 { #2 }
 }
\cs_new_protected:Npn \feklee_numprint:n #1
 {
  \numprint { #1 }
 }
\NewDocumentCommand{\numprintexpr}{m}
 {
  \feklee_numprint:n { \fp_eval:n { #1 } }
 }
\ExplSyntaxOff

\newcommand{\ratio}{round(\x/\y,2)}

\begin{document}

\fpset\x{2}
\fpset\y{3}
\numprintexpr{\ratio}

\numprintexpr{round(pi/4,8)}

\end{document}

语法不同,但比 更简单fp

在此处输入图片描述

答案2

将 x/y 值传递到宏本身:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand\ratio[3]{%
  \FPdiv#3{#1}{#2}%
  \FPround{#3}{4}{4}}

\begin{document}
\ratio{2}{3}\result
\result

\numprint{\result}
\end{document}

答案3

这个问题已经有几个答案了,但似乎没有人建议使用\edef。了解这一点可能对您在其他情况下有用,所以让我描述一下这个替代解决方案。

\edef原语与所定义的宏类似\def,但会扩展其替换文本。以下是如何重写示例:

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
}

\begin{document}
\FPset\x{2}
\FPset\y{3}
\begingroup
  \ratio
  \edef\next{\noexpand\numprint{\result}%
  \expandafter
\endgroup
\next
\end{document}

看到计算用法现在是分开的。 的工作\ratio仅限于计算比率并将其存储在宏中。

TeX 的工作方式与传统编程语言非常不同,传统编程语言可以像你之前那样编写函数。事实上,它是一种基于扩展和重写的宏语言。因此,如果你写

\numprint{\ratio}

你有绝对无法控制如何解释由 生成的标记。生成一个替换文本为 的宏\ratio会更容易,就像我在建议中所做的那样。请注意,整个代码片段实际上在处理过程中被替换。\next\numprint{0.67}\begingroup…\next\numprint{0.67}

如果您正在学习 TeX 编程,您应该考虑学习基于\edef\expandafter\noexpand寄存器的这些方法。

答案4

您要求的解决方案是保留原始文件\ratio,然后使用 打印结果\numprint。操作方法如下:

[更新:已编辑以避免全局分配]

[更新2:\fFPedef如果想要按照这个答案底部指示的方向操作,则添加的宏是必需的]

[更新3:删除了一些多余的\expandafter]

[更新 4:修正了上面的拼写错误(\fFPedef上面是我之前的选择\fFPset),只是为了将其移到列表的上部,并有机会获得更多的赞成票:)]

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

% ORIGINAL \ratio
% by convention its result is in ... \result
\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

% WRAPPER to \numprint
% Must be applied to things like \ratio which compute a \result
\def\FPnumprint #1{% 
    \setbox0 \hbox{\def\result{#1}#1\expandafter}\expandafter
    \numprint\expandafter {\result}}

\begin{document}\thispagestyle{empty}
\FPset\x{2}
\FPset\y{3}

% works
\FPnumprint {\ratio}

\newcommand{\stuff}{\FPeval\result {(\x)*(\y)+(\x)^(\y)}}

% works also

\FPnumprint {\stuff}

\end{document}

输出:

numprint 结果

顺便说一下,可以使用这种技术将所有命令转换fp.sty为可嵌套的实体:(我使用 fFP@前缀来表示fp 命令的功能形式

\documentclass{article}
\usepackage{fp}
\usepackage{numprint}

% ORIGINAL \ratio
% by convention its result is in ... \result
\newcommand{\ratio}{%
  \FPdiv\result{\x}{\y}%
  \FPround\result\result{2}%
  \result%
}

% WRAPPER to \numprint
% Must be applied to things like \ratio which compute a \result
\def\FPnumprint #1{% 
    \setbox0 \hbox{\def\result{#1}#1\expandafter}\expandafter
    \numprint\expandafter {\result}}

\makeatletter
\def\fFPadd #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPadd\fFP@result \fFP@tmpa\fFP@tmpb 
  \fFP@result
}

\def\fFPmul #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPmul\fFP@result \fFP@tmpa\fFP@tmpb 
  \fFP@result
}

\def\fFPround #1#2{%
  \setbox0 \hbox{\def\fFP@result{#1}#1\expandafter}%
  \expandafter\def\expandafter\fFP@tmpa\expandafter{\fFP@result}%
  \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
  \expandafter\def\expandafter\fFP@tmpb\expandafter{\fFP@result}%
  \FPround\fFP@tmpb\fFP@tmpb {0}%
  \FPround\fFP@result \fFP@tmpa\fFP@tmpb
  \fFP@result
}

\def\fFPnumprint #1{%
    \setbox0 \hbox {\def\fFP@result {#1}#1\expandafter}%
    \expandafter\numprint\expandafter{\fFP@result}%
}

\makeatother

\begin{document}
\FPset\x{2}
\FPset\y{3}

% works
\FPnumprint {\ratio}

\newcommand{\stuff}{\FPeval\result {(\x)*(\y)+(\x)^(\y)}}

% works also
\FPnumprint {\stuff}

\fFPadd {\fFPmul{2}{7}}{\fFPmul{3}{7}}


\fFPround {\fFPadd{\fFPmul {3.21267}{5.277282}}{16.8927287}}{2}

\fFPround {\fFPadd{\fFPmul {3.21267}{5.277282}}{16.8927287}}{\fFPadd {1}{3}}

% !!! ATTENTION !!!
% HERE We USE \fFPnumprint as we know the "result" is in "\fFP@result" not in
% "\result"

\fFPnumprint {\fFPround {\fFPadd{\fFPmul
      {3.21267}{5.277282}}{16.8927287}}{\fFPadd {1}{3}}}

\end{document}

输出:

fFP 实际作用

也许可以从这个起点出发制作一些包......因为它fp很常用。


除了上述内容之外,还需要以下类型的宏:

\makeatletter

\def\fFPedef #1#2{%
    \setbox0 \hbox{\def\fFP@result{#2}#2\expandafter}%
    \expandafter\edef\expandafter#1\expandafter{\fFP@result}%
}

\makeatother

\ttfamily

\fFPedef\x {\fFPmul{3.142627627}{\fFPadd{6.75272872}{7.832298292}}}
\meaning\x

输出:

定义

最大的区别是,正如我们在这里看到的,这些东西是可以嵌套的。

相关内容