将数字转换为字母,但以 0=A 而不是 1=A 开头

将数字转换为字母,但以 0=A 而不是 1=A 开头

正如标题所暗示的,本质上我想将数字转换为字母,并且此主题在解决这个问题上做得非常出色。

egreg 给出了一个很好的解决方案,我一直在研究它,但是尽管我研究了可以找到的相关文档,我似乎无法调整他的解决方案以输出 0=A,而不是 1=A。

这是我正在尝试使用的 egreg 解决方案之一:

\newcommand\makeAlph[1]{%
\ifcase #1\or a\or b\or c\or d\or e\or f\or g\or h\or
i\or j\or k\or l\or m\or n\or o\or p\or q\or r\or
s\or t\or u\or v\or w\or x\or y\or z\fi}

我是否可以轻松地以这种方式进行调整,或者是否有更好的解决方案适合我的具体用例?这感觉像是一件非常简单的事情,但我似乎无法确定它。

我很乐意探索任何其他提议的路线,或者在需要时提供更多细节(尽管这看起来很简单)。

谢谢!

(我也提出了相反的问题稍后介绍如何将字母转换为数字。)

答案1

语法\ifcase

\ifcase <number>
    % case 0
\or % case 1
\or % case 2
...
\else % other cases
\fi

因此,最简单的更改是放入acase 0不是放入case 1,因此只需删除第一个\or(但使用下一个选项):

\newcommand\makeAlph[1]{%
\ifcase #1 a\or b\or c\or d\or e\or f\or g\or h\or
i\or j\or k\or l\or m\or n\or o\or p\or q\or r\or
s\or t\or u\or v\or w\or x\or y\or z\fi}

您可以使其更安全一些,并且还可以使用以下方法接受数值表达式(类似于2+2)作为参数\numexpr

\newcommand\makeAlph[1]{%
\ifcase\numexpr#1\relax a\or b\or c\or d\or e\or f\or g\or h\or
i\or j\or k\or l\or m\or n\or o\or p\or q\or r\or
s\or t\or u\or v\or w\or x\or y\or z\fi}

答案2

有多种方法可以实现。一种“较新”的方法是用expl3,它有\int_to_alph:n,它接受参数中的表达式。

但是,此函数返回的字母组合值大于 26,而您并不想出现这种情况。很简单:添加一个可接受范围的测试。

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\makeAlph}{m}
 {
  \int_compare:nTF { 0 <= #1 <= 25 }
   {
    \int_to_alph:n { #1 + 1 }
   }
   {
    Bummer!
   }
 }

\ExplSyntaxOff

\begin{document}

\makeAlph{0}--\makeAlph{25}

\makeAlph{26}

\end{document}

在此处输入图片描述

如果您希望命令忽略超出范围的值,

\ExplSyntaxOn

\NewExpandableDocumentCommand{\makeAlph}{m}
 {
  \int_compare:nT { 0 <= #1 <= 25 } { \int_to_alph:n { #1 + 1 } }
 }

\ExplSyntaxOff

本质上是一行代码。

答案3

这是我LuaLaTeX基于的解决方案。我喜欢它是Lua因为Python我首选的脚本语言,而且它在语法上有很多相似之处。我很容易在心理上区分和管理编码和排版的内容。如果您想包含错误检查/抛出,例如,如果用户将 -1、28 或“alpha”传递给函数/命令,则建议的解决方案应该很容易扩展。

\documentclass{letter}
\usepackage{luacode}
\begin{luacode*}
function num2let(arg)
    local argInt = tonumber(arg)
    if argInt ~= nil then
        if  (0 <= argInt) and (argInt <= 25) then
            tex.print(string.char(65 + argInt))
        end -- can put an else statement for error tracking
    end -- can put an else statement for error tracking
end
\end{luacode*}
\newcommand{\NumToLet}[1]{\directlua{num2let(#1)}}


\begin{document}
Valid: \NumToLet{0}\NumToLet{1}...\NumToLet{25}

Invalid: \NumToLet{-1}, \NumToLet{26}, \NumToLet{alpha}
\end{document}

答案4

我可以提供一个宏

\ExtractKthArg{⟨TeX-⟨number⟩-quantity with integer-value K⟩}%
              {⟨tokens in case list of undelimited arguments doesn't have a k-th argument⟩}%
              {⟨list of undelimited arguments⟩}%

其作用如下:

如果没有⟨K⟩-th 参数⟨无界参数列表⟩:
是否提供⟨如果未限定参数列表没有第 k 个参数,则使用 tokens⟩

如果有⟨K⟩-th 参数⟨无界参数列表⟩:
确实实现了⟨K⟩-th 参数删除了一层括号。

例子:

\ExtractKthArg{0}{not available}{ABCDE}产量:not available

\ExtractKthArg{3}{not available}{ABCDE}产量: C

\ExtractKthArg{3}{not available}{AB{CD}E}产量: CD

\ExtractKthArg{4}{not available}{{001}{002}{003}{004}{005}}产量:004

\ExtractKthArg{6}{not available}{{001}{002}{003}}产量:not available

您可以轻松地定义 \makeAlph如下内容\ExtractKthArg

\newcommand\makeAlph[2]{%
   \ExtractKthArg{\number\numexpr#1+1\relax}{#2}{abcdefghijklmnopqrstuvwxyz}%
}%

这种方式\makeAlph需要参数,第一个参数是 TeX-⟨数字⟩-quantity 转换为字符,第二个参数表示在第一个参数不在 0..25 范围内时要传递的标记。

下面的最小工作示例仅依赖于\makeAlph的第一个参数是 TeX-⟨数字⟩-数量。没有检查 的\makeAlph第一个参数是否是 TeX-⟨数字⟩-quantity:第一个参数是一组标记,因此可能形成任意(基于扩展的)算法。检查执行此类算法的结果是否产生 TeX-⟨数字⟩-quantity 包括检查这种算法是否完全终止/终止时没有错误消息。这反过来让我想起了停机问题 ...
!!!\makeAlph的第一个参数不是 TeX-⟨数字⟩-数量可能会导致各种不可预测的行为,从而导致难以理解的错误消息!!!

以下是最小的工作示例:

\errorcontextlines=10000
\documentclass{article}

\makeatletter
%% Code for \ExtractKthArg
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%%    \UD@stopromannumeral, \UD@CheckWhetherNull
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{%
  \expandafter\UD@stopromannumeral\UD@firstoftwo}%
}%
%%=============================================================================
%% Extract K-th inner undelimited argument:
%%
%% \ExtractKthArg{<integer K>}%
%%               {<tokens in case list of undelimited arguments doesn't have a k-th argument>}%
%%               {<list of undelimited arguments>}%
%% 
%% In case there is no K-th argument in <list of indelimited arguments> : 
%%   Does deliver <tokens in case list of undelimited arguments doesn't have a k-th argument.
%% In case there is a K-th argument in <list of undelimited arguments> : 
%%   Does deliver that K-th argument with one level of braces removed.
%%
%% Examples:
%%
%%   \ExtractKthArg{0}{not available}{ABCDE} yields: not available
%%
%%   \ExtractKthArg{3}{not available}{ABCDE} yields:  C
%%
%%   \ExtractKthArg{3}{not available}{AB{CD}E} yields:  CD
%%
%%   \ExtractKthArg{4}{not available}{{001}{002}{003}{004}{005}} yields: 004
%%
%%   \ExtractKthArg{6}{not available}{{001}{002}{003}} yields: not available 
%% 
%%=============================================================================
\newcommand\ExtractKthArg[2]{%
  \romannumeral%
  % #1: <integer number K>
  % #2: <action if there is no K-th argument>
  \expandafter\UD@ExtractKthArgCheck
  \expandafter{\romannumeral\number\number#1 000}{#2}%
}%
\newcommand\UD@ExtractKthArgCheck[3]{%
  \UD@CheckWhetherNull{#1}{\UD@stopromannumeral#2}{% empty
    \expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}#1}{#2}{#3}%
  }%
}%
\begingroup
\def\UD@ExtractFirstArgLoop#1{%
  \endgroup
  \@ifdefinable\UD@RemoveTillFrozenrelax{%
    \long\def\UD@RemoveTillFrozenrelax##1##2#1{{##1}}%
  }%
  \newcommand\UD@ExtractKthArgLoop[3]{%
    \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo##3{}.}{\UD@stopromannumeral##2}{%
      \UD@CheckWhetherNull{##1}{%
        \UD@ExtractFirstArgLoop{##3#1}%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}##3}%
        {\expandafter\UD@ExtractKthArgLoop\expandafter{\UD@firstoftwo{}##1}{##2}}%
      }%
    }%
  }%
}%
\expandafter\expandafter\expandafter\UD@ExtractFirstArgLoop
\expandafter\expandafter\expandafter{%
\expandafter\expandafter\ifnum0=0\fi}%
%% Usage of frozen-\relax as delimiter is for speeding things up by reducing the
%% amount of iterations needed. I chose frozen-\relax because David Carlisle 
%% pointed out in   <https://tex.stackexchange.com/a/578877>
%% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be
%% affected by \uppercase/\lowercase.
%%
%% \UD@ExtractFirstArg's argument may contain frozen-\relax:
%% The only effect is that internally more iterations are needed for
%% obtaining the result.
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\expandafter\UD@stopromannumeral\UD@firstoftwo#1{}}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}%
}%
%% End of code for \ExtractKthArg.
\makeatother

\newcommand\makeAlph[2]{%
   \ExtractKthArg{\number\numexpr#1+1\relax}{#2}{abcdefghijklmnopqrstuvwxyz}%
}%

\begin{document}

\noindent
\verb|\makeAlph{0}{\makeAlpherrordefault}| yields: \makeAlph{0}{\makeAlpherrordefault}\\
\verb|\makeAlph{1}{\makeAlpherrordefault}| yields: \makeAlph{1}{\makeAlpherrordefault}\\
\verb|\makeAlph{2}{\makeAlpherrordefault}| yields: \makeAlph{2}{\makeAlpherrordefault}\\
\verb|\makeAlph{3}{\makeAlpherrordefault}| yields: \makeAlph{3}{\makeAlpherrordefault}\\
\verb|\makeAlph{4}{\makeAlpherrordefault}| yields: \makeAlph{4}{\makeAlpherrordefault}\\
\verb|\makeAlph{5}{\makeAlpherrordefault}| yields: \makeAlph{5}{\makeAlpherrordefault}\\
\verb|\makeAlph{6}{\makeAlpherrordefault}| yields: \makeAlph{6}{\makeAlpherrordefault}\\
\verb|\makeAlph{7}{\makeAlpherrordefault}| yields: \makeAlph{7}{\makeAlpherrordefault}\\
\verb|\makeAlph{8}{\makeAlpherrordefault}| yields: \makeAlph{8}{\makeAlpherrordefault}\\
\verb|\makeAlph{9}{\makeAlpherrordefault}| yields: \makeAlph{9}{\makeAlpherrordefault}\\
\verb|\makeAlph{10}{\makeAlpherrordefault}| yields: \makeAlph{10}{\makeAlpherrordefault}\\
\verb|\makeAlph{11}{\makeAlpherrordefault}| yields: \makeAlph{11}{\makeAlpherrordefault}\\
\verb|\makeAlph{12}{\makeAlpherrordefault}| yields: \makeAlph{12}{\makeAlpherrordefault}\\
\verb|\makeAlph{13}{\makeAlpherrordefault}| yields: \makeAlph{13}{\makeAlpherrordefault}\\
\verb|\makeAlph{14}{\makeAlpherrordefault}| yields: \makeAlph{14}{\makeAlpherrordefault}\\
\verb|\makeAlph{15}{\makeAlpherrordefault}| yields: \makeAlph{15}{\makeAlpherrordefault}\\
\verb|\makeAlph{16}{\makeAlpherrordefault}| yields: \makeAlph{16}{\makeAlpherrordefault}\\
\verb|\makeAlph{17}{\makeAlpherrordefault}| yields: \makeAlph{17}{\makeAlpherrordefault}\\
\verb|\makeAlph{18}{\makeAlpherrordefault}| yields: \makeAlph{18}{\makeAlpherrordefault}\\
\verb|\makeAlph{19}{\makeAlpherrordefault}| yields: \makeAlph{19}{\makeAlpherrordefault}\\
\verb|\makeAlph{20}{\makeAlpherrordefault}| yields: \makeAlph{20}{\makeAlpherrordefault}\\
\verb|\makeAlph{21}{\makeAlpherrordefault}| yields: \makeAlph{21}{\makeAlpherrordefault}\\
\verb|\makeAlph{22}{\makeAlpherrordefault}| yields: \makeAlph{22}{\makeAlpherrordefault}\\
\verb|\makeAlph{23}{\makeAlpherrordefault}| yields: \makeAlph{23}{\makeAlpherrordefault}\\
\verb|\makeAlph{24}{\makeAlpherrordefault}| yields: \makeAlph{24}{\makeAlpherrordefault}\\
\verb|\makeAlph{25}{\makeAlpherrordefault}| yields: \makeAlph{25}{\makeAlpherrordefault}

\bigskip

\noindent
\verb|\newcounter{scratchcounter}|\newcounter{scratchcounter}\\
\verb|\setcounter{scratchcounter}{12}|\setcounter{scratchcounter}{12}\\
\verb|\makeAlph{\value{scratchcounter}}{\makeAlpherrordefault}| yields: \makeAlph{\value{scratchcounter}}{\makeAlpherrordefault}

\bigskip

\noindent
% \makeAlpherrordefault delivers an error-message. Instead we want the phrase "Error-Tokens".
% \verb|\makeAlph{-1}{\makeAlpherordefault}| yields: \makeAlph{-1}{\makeAlpherordefault}\\
\verb|\makeAlph{-1}{Error-Tokens.}| yields: \makeAlph{-1}{Error-Tokens.}\\
% \verb|\makeAlph{26}{\makeAlpherrordefault}| yields: \makeAlph{26}{\makeAlpherrordefault}\\
\verb|\makeAlph{26}{Error-Tokens.}| yields: \makeAlph{26}{Error-Tokens.}

\bigskip

\noindent
\verb|\setcounter{scratchcounter}{28}|\setcounter{scratchcounter}{28}\\
%\verb|\makeAlph{\value{scratchcounter}}{\makeAlpherrordefault}| yields: \makeAlph{\value{scratchcounter}}{\makeAlpherrordefault}\\
\verb|\makeAlph{\value{scratchcounter}}{Error-Tokens.}| yields: \makeAlph{\value{scratchcounter}}{Error-Tokens.}

\end{document}

在此处输入图片描述

相关内容