Ich möchte LaTeX 3 verwenden, um automatisch zu berechnen,Medianeines Satzes vordefinierter Daten.
Betrachten Sie das folgende Beispiel:
\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}
Antwort1
Sie können Gleitkommazahlen verwenden. Der Trick besteht darin, die Werte beim Aufnehmen zu erweitern.
\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}
Antwort2
Update: l3sort
wurde in einer früheren Version verwendet, seine Makros sind expl3
jetzt darin enthalten.
Zum Glück gibt es für das Sortieren von Zahlenfolgen (ich bin hier nur von ganzzahligen Werten ausgegangen) Unterstützung in expl3
.
Der Rest ist nur Code, um die mittlere Position der Indizes zu bestimmen. In seiner jetzigen Form ist der Code jedoch nicht erweiterbar, da \seq_sort:Nn
nicht erweiterbar ist und die \int_set:Nn
Erweiterung ebenfalls verhindert.
\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}