我想使用 LaTeX 3 自動計算中位數一組預定義的資料。
考慮以下範例:
\documentclass{article}
\def\waterAa{82}
\def\waterAb{51}
\def\waterAc{144}
\def\waterAd{84}
\def\waterAe{120}
\def\waterAf{148}
\def\waterAg{148}
\def\waterAh{108}
\def\waterAi{160}
\def\waterAj{86}
\begin{document}
\noindent Consider the data set
\begin{equation}
\{\waterAa, \waterAb, \waterAc, \waterAd, \waterAe, \waterAf, \waterAg, \waterAh, \waterAi, \waterAj\}
\end{equation}
To find the median of a data set, we first have to arrange the elements relative to their values:
\begin{equation}
\{\waterAb, \waterAa, \waterAd, \waterAj, \waterAh, \waterAe, \waterAc, \waterAf, \waterAg, \waterAi\}
\end{equation}
Since the number of elements is $10$, the median~$M$ is the average of the fifth and sixth element:
\begin{equation}
M = (\waterAh+\waterAe)/2 = 114.
\end{equation}
\section*{Question}
How to I \emph{automatically} calculate the median of a data set (preferably using \LaTeX 3)?
\end{document}
答案1
可以使用浮點數;訣竅是在吸收價值的同時擴大價值。
\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\ExplSyntaxOn
\NewDocumentCommand{\median}{m}
{
\svend_median:x { #1 }
}
\clist_new:N \l__svend_median_clist
\int_new:N \l__svend_median_int
\cs_new_protected:Nn \svend_median:n
{
% set a comma separated list
\clist_set:Nn \l__svend_median_clist { #1 }
% sort it numerically
\clist_sort:Nn \l__svend_median_clist
{
\fp_compare:nTF { ##1 > ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
% compute the number of items
\int_set:Nn \l__svend_median_int { \clist_count:N \l__svend_median_clist }
\int_if_odd:nTF {\l__svend_median_int }
{% if the number is odd, return the middle item
\clist_item:Nn \l__svend_median_clist { (\l__svend_median_int + 1)/2 }
}
{% otherwise the average of the middle two elements
\fp_eval:n
{
(
\clist_item:Nn \l__svend_median_clist { \l__svend_median_int/2 }
+
\clist_item:Nn \l__svend_median_clist { \l__svend_median_int/2 + 1 }
)/2
}
}
}
\cs_generate_variant:Nn \svend_median:n { x }
\ExplSyntaxOff
\begin{document}
\def\waterAa{82}
\def\waterAb{51}
\def\waterAc{144}
\def\waterAd{84}
\def\waterAe{120}
\def\waterAf{148}
\def\waterAg{148}
\def\waterAh{108}
\def\waterAi{160}
\def\waterAj{86}
The median is \median{82,51,144,84,120,148,148,108,160,86}
The median is \median{
\waterAa, \waterAb, \waterAc, \waterAd, \waterAe,
\waterAf, \waterAg, \waterAh, \waterAi, \waterAj
}
The median is \median{
\waterAa, \waterAb, \waterAc, \waterAd, \waterAe,
\waterAf, \waterAg, \waterAh, \waterAi, %\waterAj
}
The median is \median{1,2,3,4}
The median is \median{1,2,3}
The median is \median{3.3,4.4,5.503,6.01}
The median is \median{3.3,4.4,5.503}
\end{document}
答案2
更新:l3sort
以前的版本使用過,現在包含它的巨集expl3
。
幸運的是,對於對數字序列進行排序(我僅在這裡假設整數值)expl3
,.
其餘的只是確定索引中間位置的代碼。然而,就目前情況而言,程式碼是不可擴展的,因為它\seq_sort:Nn
是不可擴展的,而且它\int_set:Nn
也阻止了擴展。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_item:Nn {NV}
\NewDocumentCommand{\median}{m}{%
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_sort:Nn \l_tmpa_seq {%
\int_compare:nNnTF { ##1 } > { ##2 }
{ \sort_reversed: }
{ \sort_ordered: }
}
\int_set:Nn \l_tmpa_int {\seq_count:N \l_tmpa_seq }
\int_if_odd:nTF { \l_tmpa_int } {%
\int_set:Nn \l_tmpb_int {\l_tmpa_int / 2}
\int_set:Nn \l_tmpa_int {\l_tmpb_int}
}{%
\int_set:Nn \l_tmpb_int {\l_tmpa_int / 2 }
\int_set:Nn \l_tmpa_int {\l_tmpb_int + 1}
}
\fp_eval:n {(\seq_item:NV \l_tmpa_seq \l_tmpb_int + \seq_item:NV \l_tmpa_seq \l_tmpa_int)/2}
}
\ExplSyntaxOff
\begin{document}
\def\waterAa{82}
\def\waterAb{51}
\def\waterAc{144}
\def\waterAd{84}
\def\waterAe{120}
\def\waterAf{148}
\def\waterAg{148}
\def\waterAh{108}
\def\waterAi{160}
\def\waterAj{86}
The median is \median{82,51,144,84,120,148,148,108,160,86}
The median is \median{\waterAa, \waterAb, \waterAc, \waterAd, \waterAe, \waterAf, \waterAg, \waterAh, \waterAi, \waterAj}
\end{document}