我想使用宏对具有不同表示形式的数字进行排序。例如 3.5%、0.321、17/5、... 如果可能的话,排序列表的输出应该再次采用相同的格式,或者 17/5 应该采用 \frac{17}{5} 格式。
不幸的是,我的知识不够,所以我想寻求帮助和建议。
通过我之前的尝试,数字已经可以排序了。但目前还不能以不同的格式排序。使用 xint,我也可以得到表示形式:17/5 -> \frac{17}{5},但之后我就无法再对列表进行排序了。
\documentclass{article}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}
\ExplSyntaxOn
\NewDocumentCommand { \Sortiere } { s m }
{
\clist_set:Nn \l_sort_clist { #2 }
\clist_sort:Nn \l_sort_clist
{
\IfBooleanTF{#1}
{ \fp_compare:nNnTF { \fp_eval:n{ ##1 } } < { \fp_eval:n{ ##2 } }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
{ \fp_compare:nNnTF { \fp_eval:n{ ##1 } } > { \fp_eval:n{ ##2 } }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
}
% \seq_new:N \l__thomas_A_seq
% \seq_clear:N \l__thomas_A_seq
% \clist_map_inline:nn { #2 }
% { \seq_put_right:Nx \l__thomas_A_seq
% { \ensuremath { \xintSignedFrac{\xintIrr { \fp_eval:n { ##1 } } } } }
% }
% \seq_use:Nn \l__thomas_A_seq {;\,}
\{\l_sort_clist\}
}
\ExplSyntaxOff
\begin{document}
\Sortiere{1,12,9/5,7.12,-3,-5,2,7,11}
\end{document}
答案1
我认为你应该将值和表示分开。你可以使用一个简单的整数序列进行排序,然后将此排序应用于其他序列(我使用了水果和数量,因为我认为如果序列包含不同的东西,更容易理解):
\documentclass{article}
\usepackage{xparse}
\begin{document}
\ExplSyntaxOn
\seq_new:N \l_th_fruit_seq
\seq_new:N \l_th_fruit_sorted_seq
\seq_set_from_clist:Nn\l_th_fruit_seq {apples,pears,pineapples,bananas}
\seq_new:N \l_th_fruitqty_seq
\seq_new:N \l_th_fruitqty_sorted_seq
\seq_set_from_clist:Nn\l_th_fruitqty_seq {10,5,20,2}
\int_zero:N\l_tmpa_int
\seq_clear:N\l_tmpa_seq
\seq_map_inline:Nn\l_th_fruit_seq % a temporary seq with 1,2,3,4 for the sorting
{
\int_incr:N\l_tmpa_int
\seq_put_right:NV\l_tmpa_seq {\l_tmpa_int}
}
\seq_sort:Nn \l_tmpa_seq %sort over the quantity
{
\int_compare:nNnTF { \seq_item:Nn\l_th_fruitqty_seq {#1} } > { \seq_item:Nn\l_th_fruitqty_seq {#2} }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\seq_map_inline:Nn \l_tmpa_seq %apply the sorting to the seqs:
{
\seq_put_right:Nx \l_th_fruit_sorted_seq { \seq_item:Nn \l_th_fruit_seq{#1} }
\seq_put_right:Nx \l_th_fruitqty_sorted_seq { \seq_item:Nn \l_th_fruitqty_seq{#1}}
}
Sorted~fruits:~\seq_use:Nn\l_th_fruit_sorted_seq {,~}
\par
Quantities:~\seq_use:Nn \l_th_fruitqty_sorted_seq {,~}
\ExplSyntaxOff
\end{document}
答案2
我可以提出以下从您自己的回答中得出的观点,我放弃了一两个选项,因为无论如何我不知道 xparse 语法。
我对 expl3 的了解有限,因此可能存在一些不太理想的地方。
想法如下:目前只有 xint 可以处理精确的分数(超过一定大小),只有 fpeval 知道对数等。因此,只需解析输入,如果有符号/
,则假设这是某个分数,并通过解析它\xintthexpr
以允许某个表达式(下面我的示例需要);如果没有,则/
通过解析数字输入fpeval
。
然后使用 xint 例程进行所有比较测试,因为它们将接受的输出作为输入\fpeval
。
我们保留原始输入以供最终打印,但(在当前版本的代码中)/
如上所述的任何内容都会触发计算\xinttheexpr
。
当然,这种方法会中断ln(2)/2
,但对于了解 xparse 和 expl3 和 regex 的人来说(不是我)触发它并不难\fpeval
。
简而言之,用进行最大限度的计算,\fpeval
但用进行所有的比较,xint
因为它允许任意大的分数。
为了简化,我删除了所有检测是否\num
可以用于格式化输出的代码,但同样,很容易添加(我也不了解 siunitx !)
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}
\ExplSyntaxOn
\clist_new:N \l_T_printnumbers_clist
\tl_new:N \l_T_parsedinput_tl
\NewDocumentCommand{ \Sortiere }{ O{} t> t! m }
{
\group_begin:
\keys_set:nn { thomas/Sortiere } { #1 }
\tl_clear:N \l_T_parsedinput_tl
\int_zero:N \l_tmpa_int
\clist_map_inline:nn { #4 }
{
\tl_set:Nn \l_tmpa_tl { ##1 }
% FIXING THE REGEX FOR \%
\regex_replace_all:nnN { \c{\%} } { /100 } \l_tmpa_tl
% (debugging) \show\l_tmpa_tl
\regex_replace_all:nnN { \c{ln} } { ln } \l_tmpa_tl
% (debugging) \show\l_tmpa_tl
\regex_replace_all:nnN { \c{sqrt} } { sqrt } \l_tmpa_tl
% notice here ##1 is tested so a /100 from a \% will be still be fp_evaluated
\regex_match:nnTF { .*/.* } { ##1 }
{
\tl_set:Nx \l_tmpa_tl { \xinttheexpr ##1 \relax }
\tl_set:Nx \l_tmpa_tl {
{ \exp_not:V \l_tmpa_tl }
{ \exp_not:N \xintSignedFrac
{ \exp_not:V \l_tmpa_tl }
}
}
}
{
\tl_set:Nx \l_tmpa_tl {
{ \fp_eval:n { \l_tmpa_tl } }
{ \exp_not:n { ##1 } }
}
}
\tl_put_right:Nx \l_T_parsedinput_tl { { \exp_not:V \l_tmpa_tl } }
}
{
%\show\l_T_parsedinput_tl
\tl_sort:Nn \l_T_parsedinput_tl
{
\IfBooleanTF{#2}
{ \xintifLt { \use_i:nn ##1 } { \use_i:nn ##2 } }
{ \xintifGt { \use_i:nn ##1 } { \use_i:nn ##2 } }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\clist_clear:N \l_T_printnumbers_clist
\tl_map_inline:Nn \l_T_parsedinput_tl
{
\clist_put_right:Nn \l_T_printnumbers_clist { \use_ii:nn ##1 }
}
\IfBooleanTF{#2}
{ \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, } }
{ \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, } }
}
\group_end:
}
\keys_define:nn { thomas/Sortiere }
{
unsort .bool_set:N = \l__T_Sortiere_unsort_bool,
unsort .initial:n = false, % Starteinstellung
unsort .default:n = true, %
round .int_set:N = \l__thomas_sortiere_round_int, % IGNORED
round .initial:n = 4,
}
\ExplSyntaxOff
\sisetup{exponent-product=\cdot}
\begin{document}
\[ \Sortiere{10, 101/10, 10.015, 3*34} \]
\[ \Sortiere{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]
\[ \Sortiere>!{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]
\[ \Sortiere{1.5\%,1,12,9/5,7.12,-3e1,-5,2,\sqrt{8}} \]
\[ \Sortiere{46296296/123456789, 370370371/987654320, (370370371/987654320 + 46296296/123456789)/2}\]
\end{document}
答案3
这是我最后尝试的。
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}
\ExplSyntaxOn
\NewDocumentCommand{ \Sortiere }{ O{} t> t! m }
{
\group_begin:
\keys_set:nn { thomas/Sortiere } { #1 }
\clist_set:Nn \l_T_numberlist_clist { #4 }
\clist_set:Nn \l_T_number_unsort_clist { #4 }
\tl_replace_all:Nnn \l_T_number_unsort_clist { \% } { /100 }
\regex_replace_all:nnN { \c{ln} } { ln } \l_T_number_unsort_clist
\bool_if:NTF \l__T_Sortiere_unsort_bool
{
\clist_clear:N \l_T_printnumbers_unsort_clist
\clist_map_inline:Nn \l_T_number_unsort_clist
{ \clist_put_right:Nn \l_T_printnumbers_unsort_clist { \ensuremath { ##1 } } }
\ensuremath {
\regex_replace_all:nnN { /100 } { \c{num}\cB\{ \1\cE\}\c{,}\c{\%} } \l_T_printnumbers_unsort_clist
\regex_replace_all:nnN { ln } { \c{ln} } \l_T_printnumbers_unsort_clist
\regex_replace_all:nnN { [+-]?\d+/[+-]?\d+ } { \c{xintSignedFrac} \cB\{ \0\cE\} } \l_T_printnumbers_unsort_clist
\regex_replace_all:nnN { [+-]?\d+e[+-]?\d+ } { \c{num} \cB\{ \0\cE\} } \l_T_printnumbers_unsort_clist
\regex_replace_all:nnN { \. } { , } \l_T_printnumbers_unsort_clist
\regex_replace_all:nnN { (sqrt)(\{[+-]?\d+\}) } { \c{sqrt} \cB\{ \2\cE\} } \l_T_printnumbers_unsort_clist
\left\{ \clist_use:Nnnn \l_T_printnumbers_unsort_clist { ;\, }{ ;\, }{ ;\, } \right\}
}
}
{
\tl_replace_all:Nnn \l_T_numberlist_clist { \% } { /100 }
\regex_replace_all:nnN { \c{ln} } { ln } \l_T_numberlist_clist
\clist_sort:Nn \l_T_numberlist_clist
{
\IfBooleanTF{#2}
{ \fp_compare:nTF { ##1 < ##2 } }
{ \fp_compare:nTF { ##1 > ##2 } }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\clist_clear:N \l_T_printnumbers_clist
\clist_map_inline:Nn \l_T_numberlist_clist
{ \IfBooleanTF{#3}
{ \clist_put_right:Nn \l_T_printnumbers_clist { \ensuremath { ##1 } } }
{ \clist_put_right:Nn \l_T_printnumbers_clist { \ensuremath { \xintSignedFrac{ \xintIrr { \xinttheexpr round ( \fp_eval:n { ##1 } ,\l__thomas_sortiere_round_int ) \relax } } } } }
}
\IfBooleanTF{#3}{
\regex_replace_all:nnN { /100 } { \c{num}\cB\{ \1\cE\}\c{,}\c{\%} } \l_T_printnumbers_clist
\regex_replace_all:nnN { ln } { \c{ln} } \l_T_printnumbers_clist
\regex_replace_all:nnN { [+-]?\d+/[+-]?\d+ } { \c{xintSignedFrac} \cB\{ \0\cE\} } \l_T_printnumbers_clist
\regex_replace_all:nnN { [+-]?\d+e[+-]?\d+ } { \c{num} \cB\{ \0\cE\} } \l_T_printnumbers_clist
\regex_replace_all:nnN { \. } { , } \l_T_printnumbers_clist
\regex_replace_all:nnN { (sqrt)(\{[+-]?\d+\}) } { \c{sqrt} \cB\{ \2\cE\} } \l_T_printnumbers_clist
}
{ }
\IfBooleanTF{#2}
{ \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, } }
{ \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, } }
}
\group_end:
}
\clist_new:N \l_T_printnumbers_clist
\clist_new:N \l_T_numberlist_clist
\clist_new:N \l_T_number_unsort_clist
\clist_new:N \l_T_printnumbers_unsort_clist
\keys_define:nn { thomas/Sortiere }
{
unsort .bool_set:N = \l__T_Sortiere_unsort_bool,
unsort .initial:n = false, % Starteinstellung
unsort .default:n = true, %
round .int_set:N = \l__thomas_sortiere_round_int,
round .initial:n = 4,
}
\ExplSyntaxOff
\sisetup{exponent-product=\cdot}
\begin{document}
\[ \Sortiere[unsort]>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, ln(17)} \]
\[ \Sortiere>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, ln(17)} \]
\[ \Sortiere[round=12]>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]
\[ \Sortiere>!{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]
\[ \Sortiere{1.5\%,1,12,9/5,7.12,-3e1,-5,2,sqrt{8}} \]
\[ \Sortiere[unsort]!{1.5\%,1,12,-11/5,7.12,-3e1,-5,2,sqrt{8}} \]
\end{document}