带有 fp 包的数组变量:如何在数组中使用 \FPeval?

带有 fp 包的数组变量:如何在数组中使用 \FPeval?

我想将数组和fp包一起使用。

\FPadd\xx{\somevalues(1)}{\somevalues(3)} 效果很好

\FPeval\xx{\somevalues(1)+\somevalues(1)}不工作

如何在数组中使用 \FPeval?

\documentclass{article}
\usepackage{fp}
\usepackage{siunitx,amsmath}
%\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newarray}{m}
 {
  \seq_new:c { l_hafid_array_ \cs_to_str:N #1 _seq }
  \cs_new:Npn #1 (##1)
   {
    \seq_item:cn { l_hafid_array_ \cs_to_str:N #1 _seq } { ##1 }
   }
 }
\NewDocumentCommand{\readarray}{mm}
 {
  \seq_set_split:cnn { l_hafid_array_#1_seq } { & } { #2 }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { c }
\ExplSyntaxOff

\begin{document}

\newarray\somevalues
\readarray{somevalues}{1&2&3.5&4&5}

\begin{align*}
v_1 &= \somevalues(1)\\
v_2 &= \somevalues(2)\\
v_3 &= \somevalues(3)\\
v_4 &= \somevalues(4)\\
v_5 &= \somevalues(5)
\end{align*}

First number = \somevalues(1)\\
Second number = \somevalues(2)

\FPadd\xx{\somevalues(1)}{\somevalues(2)}
\FPeval{\xx}{round(xx,4)}%
sum of first two numbers = \xx

\FPeval\xx{\somevalues(1)+\somevalues(2)}
\FPeval{\xx}{round(xx,4)}%
sum of first two numbers = \xx


%
\newcount\count
\count=5
\FPset\ans{0}
\loop
%\somevalues(\count)\\
\FPadd\ans{\ans}{\somevalues(\count)}
%\FPeval\ans{\ans+\somevalues(\count)}
\advance \count by -1
\unless\ifnum \count<1
\repeat
%
\FPeval{\ans}{round(ans,4)}%
sum of all numbers = \ans

\end{document}

答案1

您的代码无法正常工作,因为包解析其输入的方式fp。在 TeX 中,当您定义分隔宏时,分隔符文本必须总是存在,所以\somevalues后面必须始终跟着一个(,然后是一些文本,然后是一个结束的)。当fp尝试解析您的表达式时,它会分隔标记并在其间添加其他标记,那么您得到的错误是:

! Use of \somevalues doesn't match its definition.
<argument> \somevalues  
                        \FP@gen@code {2}

因为接下来的\somevalues\FP@gen@code,不是(

既然你正在使用,expl3那么你可以使用它的l3fp模块,它提供了一个可扩展的 FP 引擎。可扩展意味着你可以做

The~value~of~$\pi^2$~is:~\fp_eval:n { pi^2 }

甚至

\setlength{\textwidth}{\fp_eval:n{ 10*30 } pt}

这里我模拟了fp的宏\FPadd\FPset\FPeval使用 来l3fp代替。请注意,这些模拟的宏不再可扩展。

现在您可以这样做,例如:

\FPset\ans{5}
\FPeval\ans{ans+10}
ans is: \ans % prints 15

每一个宏,比如说\ans,用作 的第一个参数,都是\FP<something>用操作的结果定义的,加上一个称为 的FP字,ans是定义的,并将包含相同的值,因此在表达式中你可以使用\ansans

警告!如果所涉及的宏已经定义,则不会执行任何验证,因此您可能会意外覆盖一些重要内容。这\FPeval\pi{6.283185}可能不是一个好主意。

这是代码(我只改变了 FP 函数的定义;您的数组处理和测试代码是相同的):

\documentclass{article}
% \usepackage{fp}
\usepackage{siunitx,amsmath}
%\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newarray}{m}
 {
  \seq_new:c { l_hafid_array_ \cs_to_str:N #1 _seq }
  \cs_new:Npn #1 (##1)
   {
    \seq_item:cn { l_hafid_array_ \cs_to_str:N #1 _seq } { ##1 }
   }
 }
\NewDocumentCommand{\readarray}{mm}
 {
  \seq_set_split:cnn { l_hafid_array_#1_seq } { & } { #2 }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { c }


% Stolen from l3fp:
\fp_new:N \l__sandu_temp_fp
\cs_set_protected:Npn \sandu_fp_name:nn #1 #2
  {
    \cs_undefine:c { c__sandu_#1_fp }
    \fp_const:cn { c__sandu_#1_fp } { #2 }
    \__sandu_define_fp_name:cn { c__sandu_#1_fp } { #1 }
  }
\cs_new_protected:Npn \__sandu_define_fp_name:Nn #1 #2
  {
    \cs_set:cpn { __fp_parse_word_#2:N }
      { \exp_after:wN #1 \exp:w \exp_end_continue_f:w \__fp_parse_infix:NN }
  }
\cs_generate_variant:Nn \__sandu_define_fp_name:Nn { c }
\cs_generate_variant:Nn \sandu_fp_name:nn { f }


% Emulating fp.sty
\NewDocumentCommand \FPadd {m mm}
  {
    \tl_set:Nx #1 { \fp_eval:n { #2 + #3 } }
    \sandu_fp_name:fn { \cs_to_str:N #1 } { #1 }
  }
\NewDocumentCommand \FPeval {m m}
  {
    \tl_set:Nx #1 { \fp_eval:n { #2 } }
    \sandu_fp_name:fn { \cs_to_str:N #1 } { #1 }
  }
\NewDocumentCommand \FPset {m m}
  {
    \tl_set:Nx #1 { \fp_eval:n { #2 } }
    \sandu_fp_name:fn { \cs_to_str:N #1 } { #1 }
  }
\ExplSyntaxOff

\begin{document}

\newarray\somevalues
\readarray{somevalues}{1&2&3.5&4&5}

\begin{align*}
v_1 &= \somevalues(1)\\
v_2 &= \somevalues(2)\\
v_3 &= \somevalues(3)\\
v_4 &= \somevalues(4)\\
v_5 &= \somevalues(5)
\end{align*}

First number = \somevalues(1)\\
Second number = \somevalues(2)

\FPadd\xx{\somevalues(1)}{\somevalues(2)}
\FPeval{\xx}{round(xx,4)}%
sum of first two numbers = \xx

\FPeval\xx{\somevalues(1)+\somevalues(2)}
\FPeval{\xx}{round(xx,4)}%
sum of first two numbers = \xx


%
\newcount\counter
\counter=5
\FPset\ans{0}
\loop
%\somevalues(\counter)\\
\FPadd\ans{\ans}{\somevalues(\counter)}
%\FPeval\ans{\ans+\somevalues(\counter)}
\advance \counter by -1
\unless\ifnum \counter<1
\repeat
%
\FPeval{\ans}{round(ans,4)}%
sum of all numbers = \ans

\end{document}

打印结果为:

在此处输入图片描述


PS:不要这样做,\newcount\count因为您将重新定义 TeX 原语\count。请使用其他名称。

答案2

不要使用\newcount如果您不知道它的怪癖:例如,它不检查控制序列是否已定义。如果您想要另一个壮观的残骸,请尝试\newcount\box

你混淆了语法。比如

\newarray\somevalues
\setarray\somevalues{1&2&3}

\somevalues(1)

很时髦arrayjobx,我不会用,因为它会让解析器感到困惑\fpeval。更好的标准参数分隔符是括号。

fp当您已经在使用时,无需再使用expl3

\documentclass{article}
\usepackage{siunitx,amsmath}
\usepackage{xparse,xfp}

\ExplSyntaxOn
\NewDocumentCommand{\newarray}{m}
 {
  \seq_new:c { l_hafid_array_#1_seq }
  \cs_new:cpn { #1 } ##1
   {
    \seq_item:cn { l_hafid_array_#1_seq } { ##1 }
   }
 }
\NewDocumentCommand{\readarray}{mm}
 {
  \seq_set_split:cnn { l_hafid_array_#1_seq } { & } { #2 }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { c }

\NewExpandableDocumentCommand{\sumarray}{O{15}m}
 {
  \fp_eval:n { round( \seq_use:cn { l_hafid_array_#2_seq } { + }, #1 ) }
 }

\ExplSyntaxOff

\begin{document}

\newarray{somevalues}
\readarray{somevalues}{1&2&3.5&4&5}

\begin{align*}
v_1 &= \somevalues{1}\\
v_2 &= \somevalues{2}\\
v_3 &= \somevalues{3}\\
v_4 &= \somevalues{4}\\
v_5 &= \somevalues{5}
\end{align*}

First number = \somevalues{1}

Second number = \somevalues{2}

sum of first two numbers = 
\fpeval{ round(\somevalues{1}+\somevalues{2},4) }

Sum of the array \sumarray[4]{somevalues}

Sum of the array \sumarray[0]{somevalues}

\end{document}

可选参数\sumarray是四舍五入的位数。

在此处输入图片描述

相关内容