在编写包含许多数字序列(以及各种下限和上限)的文档时,我想定义一个命令,如下\myscale{1}{6}
所示:
1 2 3 4 5 6
我想知道如何创建while
循环来写入数字直到达到第二个参数给出的值...有什么想法吗?
答案1
没有任何包,只有经典的 TeX:
\newcount\tmpnum
\def\myscale#1#2{%
\tmpnum=#1 \the\tmpnum
\loop
\ifnum\tmpnum<#2
\advance\tmpnum by1
\quad\the\tmpnum
\repeat
}
使用 eTeX 扩展和 axpandable 解决方案:
\def\myscale#1#2{#1%
\ifnum#1<#2 \space \expandafter\myscale\expandafter{\the\numexpr#1+1\relax}{#2}\fi
}
编辑:第三个版本添加了下面评论中 jfbu 描述的功能。即首先评估参数,然后\if...\fi
解决嵌套问题。
\def\myscale#1#2{\expandafter\myscaleA\expandafter{\the\numexpr#1\expandafter}%
\expandafter{\the\numexpr#2}% evaluate params
}
\def\myscaleA#1#2{#1\ifnum#1<#2 \space \myscaleB{\the\numexpr#1+1\relax}{#2}\fi}
\def\myscaleB#1\fi{\fi \expandafter\myscaleA\expandafter#1}
答案2
无需任何软件包(但需要 e-TeX),完全可扩展的解决方案:
\documentclass{article}
\makeatletter
\newcommand{\myscale}[2]{%
\ifnum#1=#2
$#1$\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\myscale@aux{#1}{#2}}%
}
\newcommand{\myscale@aux}[2]{%
\ifnum#1>#2
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\myscale@neg{#1}{#2}}%
{\myscale@pos{#1}{#2}}%
}
\newcommand{\myscale@neg}[2]{%
$#1$\expandafter\myscale@neg@aux\expandafter{\the\numexpr#1-1}{#2}%
}
\newcommand{\myscale@neg@aux}[2]{%
\ifnum#1<#2
\expandafter\@gobble
\else
\space$#1$\expandafter\@firstofone
\fi
{\expandafter\myscale@neg@aux\expandafter{\the\numexpr#1-1}{#2}}%
}
\newcommand{\myscale@pos}[2]{%
$#1$\expandafter\myscale@pos@aux\expandafter{\the\numexpr#1+1}{#2}%
}
\newcommand{\myscale@pos@aux}[2]{%
\ifnum#1>#2
\expandafter\@gobble
\else
\space$#1$\expandafter\@firstofone
\fi
{\expandafter\myscale@pos@aux\expandafter{\the\numexpr#1+1}{#2}}%
}
\makeatother
\begin{document}
\myscale{1}{6}
\myscale{1}{1}
\myscale{6}{1}
\myscale{1}{-1}
\edef\temp{\myscale{1}{6}}
\texttt{\meaning\temp}
\end{document}
带有用于不同格式的可选参数(当然不可扩展)。第一个可选参数\myscale
是分隔符(默认为空格);第二个参数是最后两个项目之间的分隔符(默认与第一个参数相同);如果指定,则第三个参数将用于多个项目中的最后两个项目之间,如果只有两个项目(例如牛津逗号),则使用第二个参数。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\myscale}{O{~}oomm}
{
\IfNoValueTF{#2}
{
\alain_myscale:nnnnn { #1 } { #1 } { #1 } { #4 } { #5 }
}
{
\IfNoValueTF{#3}
{ \alain_myscale:nnnnn { #2 } { #1 } { #2 } { #4 } { #5 } }
{ \alain_myscale:nnnnn { #2 } { #1 } { #3 } { #4 } { #5 } }
}
}
\seq_new:N \l_alain_myscale_seq
\cs_new_protected:Nn \alain_myscale:nnnnn
{
\seq_clear:N \l_alain_myscale_seq
\int_step_inline:nnnn { #4 } { \int_compare:nTF { #4 > #5 } { -1 } { 1 } } { #5 }
{
\seq_put_right:Nn \l_alain_myscale_seq { $##1$ }
}
\seq_use:Nnnn \l_alain_myscale_seq { #1 } { #2 } { #3 }
}
\ExplSyntaxOff
\begin{document}
\myscale{1}{6}
\myscale[, ]{1}{6}
\myscale[, ][ and ]{1}{6}
\myscale[, ][ and ][, and ]{1}{6}
\myscale{1}{1}
\myscale{6}{1}
\myscale{1}{-1}
\end{document}
答案3
这是一个基于 LuaLaTeX 的解决方案。 的两个参数\myscale
可以是任何在 TeX 和 Lua 的组合规则下求值为数字的表达式。 如果宏的第二个参数小于第一个参数,则不会打印任何内容。
% !TEX TS-program = lualatex
\documentclass{article}
\newcommand{\myscale}[2]{\directlua{%
for i = #1, #2 do tex.print(i) end}}
\newcommand\myvar{1}
\begin{document}
\myscale{1}{6} % integers from 1 to 6
\myscale{1+\myvar}{2*2^3} % integers from 2 to 16
\myscale{1}{0} % nothing is printed
\end{document}
附录: 如果减少允许算术序列(在这种情况下的第二个参数\myscale
小于第一个参数),需要将Luafor
循环的可选第三个参数——控制增量的步长——设置为-1
。
% !TEX TS-program = lualatex
\documentclass{article}
\newcommand\myscale[2]{\directlua{%
local incr = 1
if #1 > #2 then incr = -1 end % set to -1 if decreasing sequence
for i = #1, #2, incr do tex.print(i) end}}
\newcommand\myvar{1} % a dummy macro
\begin{document}
\myscale{1}{6}
\myscale{math.log(1)}{2^3-\myvar}
\myscale{\myvar+2^math.exp(0)}{math.log(\myvar)}
\end{document}
答案4
\whiledo
包装的 使用 ifthen
:
\documentclass{article}
\usepackage{ifthen}
\newcounter{mycount}
\newcommand{\myscale}[2]{
\setcounter{mycount}{#1}
\whiledo{\value{mycount}<#2}
{\arabic{mycount}, \stepcounter{mycount}}%
\arabic{mycount}.}
\begin{document}
\myscale{1}{6}\par
\myscale{-4}{4}
\end{document}
或者使用以下forloop
包:
\documentclass{article}
\usepackage{forloop}
\newcounter{mycount}
\newcommand{\myscale}[2]{
\setcounter{mycount}{#1}
\forloop{mycount}{#1}{\value{mycount} < #2}%
{\arabic{mycount}, }%
\arabic{mycount}.}
\begin{document}
\myscale{1}{6}\par
\myscale{-4}{4}
\end{document}