代码就这样了,剩下的该怎么完成呢?
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand{\average}{m}{%
}
\ExplSyntaxOff
\average{1,3.7,5} % would return 3.233
\average{1,3.7,5,3.2*2,7.9} % would return 4.8. the argument number is arbitrary but limited
\end{document}
0
5 个回答
5
要创建一个 expl3 命令来计算几个数字的平均值,包括像 3.2*2 这样的表达式,您可以使用以下代码:
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand{\average}{m}{%
\average_numbers:n {#1}
}
\cs_new_protected:Nn \average_numbers:n {
% Parse the argument into a sequence
\seq_set_from_clist:Nn \l__average_numbers_seq { #1 }
% Initialize sum and count variables
\fp_zero_new:N \l__average_sum_fp
\int_zero_new:N \l__average_count_int
% Iterate over the sequence
\seq_map_inline:Nn \l__average_numbers_seq {
% Increase the count
\int_incr:N \l__average_count_int
% Evaluate the expression and add to sum
\fp_add:Nn \l__average_sum_fp { \fp_eval:n { ##1 } }
}
% Compute the average
\fp_div:Nn \l__average_sum_fp { \int_use:N \l__average_count_int }
% Output the average
\fp_use:N \l__average_sum_fp
}
\ExplSyntaxOff
\average{1,3.7,5} % returns 3.233333333333333
\average{1,3.7,5,3.2*2,7.9} % returns 4.8
\end{document}
此代码定义了一个新命令 \average,该命令接受以逗号分隔的数字或表达式列表。它计算已求值的表达式的总和,计算项目数,并通过将总和除以计数来计算平均值。然后使用 \fp_use:N 打印结果
这有帮助吗?:)
1
-
1这似乎无法编译。
–
|
下面定义了\average
宏的完全可扩展变体。我还添加了一个可选参数来提供舍入精度。
您不需要任何其他东西来访问变量,无论它们定义为宏还是fp
变量。
\documentclass{article}
\ExplSyntaxOn
\cs_new:Npn \xcn_mean:n #1
{ \fp_eval:n { ( \clist_use:nn {#1} { + } ) / \clist_count:n {#1} } }
\NewExpandableDocumentCommand \average { o m }
{
\IfNoValueTF {#1}
{ \xcn_mean:n {#2} }
{ \fp_eval:n { round ( \xcn_mean:n {#2}, #1 ) } }
}
\fp_new_variable:n { aaa }
\fp_set_variable:nn { aaa } { 3.7 }
\ExplSyntaxOff
\begin{document}
\average[3]{1,aaa,5} % would return 3.233
\average{1,3.7,5,3.2*2,7.9} % would return 4.8. the argument number is arbitrary but limited
\end{document}
扩展变体还允许计算函数返回值的平均值。我使用expkv-cs
将可选参数拆分为具有两个键round
和的 key=value 参数f
。键定义列表中的符号与中的键和其他相关包中的符号V:~
相同(请注意,只能在中使用,在该范围之外应该是)。\exp_args:NV
expkv
~
\ExplSyntaxOn
V:
\documentclass{article}
\usepackage{expkv-cs}
\ExplSyntaxOn
\cs_new:Npn \xcn_mean:n #1
{ \fp_eval:n { ( \clist_use:nn {#1} { + } ) / \clist_count:n {#1} } }
\cs_new:Npn \xcn_mean_function:nn #1#2
{
\fp_eval:n
{
( \clist_map_tokens:nn {#2} { \__xcn_mean_function_aux:nn {#1} } )
/ \clist_count:n {#2}
}
}
\cs_new:Npn \__xcn_mean_function_aux:nn #1#2 { +(#1(#2)) }
\NewExpandableDocumentCommand \average { O{} m }
{ \__xcn_average:nn {#1} {#2} }
\ekvcSplitAndForward \__xcn_average:nn \__xcn_average_aux:nnn
{
V:~ round = \c_novalue_tl
,V:~ f = \c_novalue_tl
}
\cs_new:Npn \__xcn_average_aux:nnn #1#2#3
{
% #1: round
% #2: f
% #3: clist
\tl_if_novalue:nTF {#1}
{ \__xcn_average_aux:nn {#2} {#3} }
{ \fp_eval:n { round ( \__xcn_average_aux:nn {#2} {#3}, #1 ) } }
}
\cs_new:Npn \__xcn_average_aux:nn #1#2
{
\tl_if_novalue:nTF {#1}
{ \xcn_mean:n {#2} }
{ \xcn_mean_function:nn {#1} {#2} }
}
\fp_new_variable:n { aaa }
\fp_set_variable:nn { aaa } { 3.7 }
\fp_new_function:n { sq }
\fp_set_function:nnn { sq } { x } { x**2 }
\ExplSyntaxOff
\begin{document}
\average[round=3]{1,aaa,5} % would return 3.233
\average{1,3.7,5,3.2*2,7.9} % would return 4.8. the argument number is arbitrary but limited
\average[f=sq]{1, 2, 3, 4} % 30/4 = 7.5
\end{document}
4
-
是否可以访问 \average 中的每个项目并制作一个使用循环逐个添加项目的程序?
– -
@XCN 你为什么要这样做?我看不出有什么好处,
\clist_use:nn {#1} { + }
代码非常简单简洁。当然可以手动循环,正如我所说,我只是看不出这样做的理由。
– -
如果我需要一个函数并且已知变量存储在列表中,那么它需要访问该项目。
– -
@XCN 仅对于变量来说你不需要这样做,但是如果你想要依次获得应用于每个项目的函数的平均值,那么你是对的。请参阅我的最新编辑,其中增加了这种可能性。
–
|
可以使用和\average
在 OpTeX 中创建可扩展宏:\expr
\foreach
\optdef\average[3]#1{\immediateassignment\tmpnum=0
\expr[\the\opt]{(0\foreach#1,\do##1,{+(##1)\incrtmpnum})/\the\tmpnum}}
\def\incrtmpnum{\immediateassignment\advance\tmpnum by1 }
\average{1,3.7,5} % would return 3.233
\average[1]{1,3.7,5,3.2*2,7.9} % would return 4.8. the argument number is arbitrary but li
\message{\average[5]{2,3}}
\bye
|
很难跟随你沿着 fp 变量的旅程……
但是,可以定义一个可扩展的\average
命令来应对各种方法。
\documentclass{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\average}{O{20}m}
{% #1 = accuracy, #2 = list of fp expressions
\xcn_average:nn {#1} {#2}
}
\cs_new:Nn \xcn_average:nn
{
\fp_eval:n { round ( 0 \clist_map_function:nN {#2} \__xcn_average_item:n , #1 ) }
}
\cs_new:Nn \__xcn_average_item:n
{
+ \fp_eval:n {#1}
}
%% method with fp variables
\fp_new_variable:n { aaa }
\fp_set_variable:nn { aaa } { 3.5 }
% method with commands
\newcommand{\bbb}{4.5}
\ExplSyntaxOff
\begin{document}
\average{2,4,aaa,\bbb,pi}
\average[3]{2,4,aaa,\bbb,pi}
\edef\test{\average[4]{2,4,aaa,\bbb,pi}}
\texttt{\meaning\test}
\end{document}
5
-
好像我表达不清楚,我的目的是,如果我计算
z=2*x+3*y
,让x=5,y=6,然后定义一个可以计算z的函数,并将{5,6}作为列表供expl3使用,结果为2*5+3*6=28
。
–
-
4这还不算是平均值,是吗?
– -
是的,这超出了主题的范围。
– -
什么
O{20}
意思?保留20位小数?为什么中有一个0round(0 \clist_…
?
– -
@XCN 由于小数位数最多为 15,因此使用 20 与打印整数没什么不同。您可以决定始终舍入的开销是否比检查可选参数的开销更大。
–
|
如果重点是学习 expl3,那么这是错误的答案。但如果目标是使描述性统计数据变得简单,如平均值或中位数,或者更复杂,请考虑在 LateX 文档中包含 R 语言:
文件名:mwe.Rnw (本地,在 Overleaf 中使用mwe.Rtex )
\documentclass{article}
\parskip1em\parindent0pt
\begin{document}
<<echo=F>>=
require(knitr)
@
Mean of \Sexpr{combine_words(c(1,3.7,5))} would return roughly
\Sexpr{round(mean(c(1,3.7,5)),2)} (more precisely,
\Sexpr{mean(c(1,3.7,5))})
<<data,echo=F>>=
# complex data better in a object x
x <- c(1,3.7,5,3.2*2,7.9)
@
Mean of x values (\Sexpr{x}) is \Sexpr{mean(x)} with a SD of
\Sexpr{sd(x)} (rounded \Sexpr{round(sd(x),1)}) but the median is
\Sexpr{median(x)}.
<<echo=F,fig.cap="Average of x in a box and wisker plot",fig.pos="h!">>=
boxplot(x,xlab="My x values")
@
\end{document}
0
|
|