Array variable with fp package: How to use \FPeval in array?

Your code does not work because the way that the fp package parses its input. In TeX when you define a delimited macro the delimiter text must always be present, so \somevalues must always be followed by a (, then some text, then a closing ). When fp tries to parse your expression it separates the tokens and adds other tokens in between, then the error you get is:

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

because what follows \somevalues is \FP@gen@code, not a (.

Since you're using expl3 anyway you can use its l3fp module, which offers an expandable FP engine. Being expandable means that you can do

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

or even

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

Here I emulated fp's macros \FPadd, \FPset and \FPeval using l3fp instead. Note that these emulated macros aren't expandable anymore.

Now you can do, for instance:

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

Every macro, say, \ans, used as the first argument to \FP<something> is defined with the result of the operation, plus a FP word called ans is defined and will contain that same value, so inside an expression you can use either \ans or ans.

CAUTION! This does not perform any verification whatsoever if the involved macros are already defined, so you can accidentally overwrite something important. \FPeval\pi{6.283185} might not be a good idea.

Here's the code (I only changed the definitions of the FP functions; your array handling and test code is the same):

\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}

which prints:

enter image description here


P.S.: Don't do \newcount\count because you'll redefine the TeX primitive \count. Use another name.


Don't use \newcount if you don't know about its quirks: for instance, it doesn't check whether the control sequence is already defined. If you want another spectacular wreckage, try \newcount\box.

You're mixing syntaxes. Something like

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

\somevalues(1)

is in arrayjobx style and is not something I'd use, because it can confuse the parser for \fpeval. Better standard argument delimiters, that is, braces.

There is no need to use fp when you're already using 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}

The optional argument to \sumarray is the number of digits for the rounding.

enter image description here

Tags:

Fp