使用 siunitx 自定义数字分组

使用 siunitx 自定义数字分组

考虑这个简单的例子。

\documentclass[12pt]{standalone}
\usepackage{siunitx}
\begin{document}
\begin{tabular}{S[group-separator={,}]}
  123456789
\end{tabular}

显示为

123,456,789

在印度数字系统中,数字的分组略有不同。引用维基百科文章 小数分隔符

印度的数字系统稍微复杂一些:它将最右边的三位数字组合在一起(直到百位),然后按两位数字的集合进行分组。例如,一万亿 [ 10^{12}] 因此可以写为10,00,00,00,00,000或 10 kharab。

在这个特定的例子中,我想将数字分组为

12,34,56,789

更一般地,支持将数字分组为任意长度的组可能会很有用。如果没有这样的支持,解决方法/黑客可能会有所帮助。

请参阅相关的 GitHub 问题,功能要求:组分隔符以可变的数字分隔

答案1

以下解决方案以“印度风格”(因为没有更好的术语)格式化大数字(准确地说是正整数)。该解决方案提供了一个名为的用户宏\indnum,它依赖于 Lua 的字符串库,因此必须在 LuaLaTeX 下编译。

这种格式化方法与包兼容siunitx,因为解决方案实际上依赖于\num宏来格式化小于 100,000 的数字——哎呀,1,00,000。但是,数字不能直接用于类型的列中S。另一方面,的参数不必是显式整数;只要参数根据 Lua 的语法规则计算为数字,\indnum就可以输入诸如 之类的内容。2e8*4+20/4

补充说明:您在评论中声称“siunitx的功能的一部分是数字格式”。就我个人而言,我实际上非常不同意您的说法——我会立即将其改为“siunitx的功能之一是数字格式根据公认的 SI 原则“[强调]。我所知道的唯一这样的原则是以 1000 的乘法增量进行分组。在我看来,所有其他分组方法——包括大于 999 的数字以 100 的乘法增量——都不在该siunitx软件包应该关注的范围内。当然,我很乐意让 Joseph Wright(该软件包的作者和维护者siunitx)就这个问题发表自己的看法。

无论如何,我不明白为什么不能使用r列类型来排版“印度风格”格式的数字。请参阅下表了解应用程序。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article} % or some other suitable document class
\usepackage[group-separator={,},
            group-minimum-digits=4,
            input-decimal-markers={.}]{siunitx}

\usepackage{luacode} % for "luacode" environment
\begin{luacode}
function indnum ( n )
   local s, t
   n = math.floor ( n ) -- retain integer part
   if n<1e5 then -- invoke "\num" macro to format and print
      tex.sprint ( "\\num{" .. n .. "}" )
   else
      s = string.reverse ( "" .. n ) -- convert to string & reverse
      t = s:sub(1,3) .. "," .. s:sub(4,5) .. ","
      s = s:sub(6) -- discard first 5 digits of 's' string
      while #s > 2 do
         t = t .. s:sub(1,2) .. ","
         s = s:sub(3) -- discard first 2 digits of 's' string
      end
      t = t .. s -- last step: 's' contains 0, 1, or 2 digits
      tex.sprint ( string.reverse ( t ) ) -- reverse order and print
   end
end
\end{luacode}
\newcommand\indnum[1]{\directlua{ indnum(#1) }}

\begin{document}
\begin{tabular}{r l}
  \indnum{500}\\
  \indnum{5e4}\\
  \indnum{1e5} & 1 lakh\\
  \indnum{1e7} & 1 crore\\
  \indnum{2e8*4+20/4}\\
  \indnum{123456789e1}\\
  \indnum{123456789e2}\\
  \indnum{123456789e3}\\
  \indnum{123456789e4}
\end{tabular}
\end{document}

答案2

一种可能:效率不高并且使用内部方法,但目前这是唯一的方法:

\documentclass{article}
\usepackage{siunitx}
\ExplSyntaxOn
\cs_gset:Npn \__siunitx_number_output_integer_aux:n #1
  {
    \int_compare:nNnTF { \tl_count:n {#1} } > 3
      {
        \exp_args:Ne \__siunitx_number_output_integer_auxii:n
          { \tl_reverse:n {#1} }
      }
      { \exp_not:n {#1} }
  }
\cs_new:Npn \__siunitx_number_output_integer_auxii:n #1
  {
    \__siunitx_number_output_integer_auxiii:w #1
      \q_recursion_tail \q_recursion_tail \q_recursion_stop
    \__siunitx_number_output_integer_end:n { }
  }
\cs_new:Npn \__siunitx_number_output_integer_auxiii:w #1#2#3
  {
    \__siunitx_number_output_integer_store:nw {#3#2#1}
    \__siunitx_number_output_integer_auxiv:w
  }
\cs_new:Npn \__siunitx_number_output_integer_auxiv:w #1#2
  {
    \quark_if_recursion_tail_stop:N #1
    \quark_if_recursion_tail_stop_do:Nn #2
      { \__siunitx_number_output_integer_store:nw {#1} }
    \__siunitx_number_output_integer_store:nw
      {
        #2#1
        \str_if_eq:VnTF \l__siunitx_number_group_separator_tl { , }
          { \exp_not:N \mathord }
          { \use:n }
            { \exp_not:V \l__siunitx_number_group_separator_tl }
      }
    \__siunitx_number_output_integer_auxiv:w
  }
\cs_new:Npn \__siunitx_number_output_integer_end:n #1
  { \exp_not:n {#1} }
\cs_new:Npn \__siunitx_number_output_integer_store:nw
  #1#2 \__siunitx_number_output_integer_end:n #3
  {
    #2
    \__siunitx_number_output_integer_end:n {#1#3}
  }
\ExplSyntaxOff

\begin{document}
\begin{tabular}{S[group-separator={,}]}
  123456789
\end{tabular}
\end{document}

答案3

您可以使用选项指定第一个组和后续组的大小:

    digit-group-first-size=3,
    digit-group-other-size=2,
    group-separator={,},

下面,我定义\numI使用上述选项并在第二行产生结果的宏:

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{siunitx}

\sisetup{group-minimum-digits=4}
\newcommand{\numI}[1]{%
    \num[
        digit-group-first-size=3,
        digit-group-other-size=2,
        group-separator={,},
    ]{#1}%
}

\begin{document}

Default: $\num{123456789}$

Indian: $\numI{123456789}$

\end{document}

相关内容