4

As a first step I am calculating the sum of a series of numbers. Then I want to calculate the root of the sum, but I don't know how to use the result.

So I tried using \def\test{\calcsum{\one,\two,\three}} and calling with \calcroot{\test} but it doesn't work. (The code for this is from LATEX3: More than 9 arguments.)

It gives me the error message:

You can't use \edef after \the. \cs_set_nopar_Npx

Does someone know how to fix this? Thanks in Advance!

\documentclass[a4paper,12pt]{article}
\usepackage{xparse}
\usepackage{fp}

\def\one{1}
\def\two{2}
\def\three{3}
\def\four{4}
\def\five{5}
\def\six{6}
\def\seven{}
\def\eight{8}
\def\nine{9}
\def\ten{1}

\ExplSyntaxOn
\NewDocumentCommand{\calcsum}{m}
{
\clist_set:Nx \l_tmpa_clist { #1 }
\fp_to_decimal:n { \clist_use:Nn \l_tmpa_clist { + } }
}
\ExplSyntaxOff

 \def\test{\calcsum{\one,\two,\three}}


\ExplSyntaxOn
\NewDocumentCommand{\calcroot}{m}
 { \fp_eval:n {sqrt(#1)}}               
 \ExplSyntaxOff

 \begin{document}

 \calcroot{\test}


 \end{document}
3
  • as last time you have \seven empty is that intentional? (it complicates things a bit as 6++8 would be a syntax error) also you probably don't need fp package if you are loading expl3 via xparse as expl3 has its own floating point implementation. Commented Dec 13, 2016 at 11:23
  • @DavidCarlisle Yes it is intentional, because i need to calculate the sum of a column in a table even if the entry is empty.
    – ChrisF
    Commented Dec 13, 2016 at 11:30
  • If you are using emacs as editor, have a look at the spreadsheet feature, e.g. here: orgmode.org/manual/A-LaTeX-example.html#A-LaTeX-example -- To me it seems by far easier to maintain tabulars as orgtbl than this here.
    – Keks Dose
    Commented Dec 13, 2016 at 13:32

2 Answers 2

3

You can't use \calcsum as a piece of a computation, because it does assignments; since you seem to be using the various pieces in different places, you can define \calcsum with an optional argument which represents a variable where to store the result; if not present, the value is just printed.

\documentclass[a4paper,12pt]{article}
\usepackage{xparse}
\usepackage{fp}

\def\one{1}
\def\two{2}
\def\three{3}
\def\four{4}
\def\five{5}
\def\six{6}
\def\seven{}
\def\eight{8}
\def\nine{9}
\def\ten{1}

\ExplSyntaxOn
\NewDocumentCommand{\calcsum}{om}
 {
  \clist_set:Nx \l_tmpa_clist { #2 }
  \IfNoValueTF{#1}
   {
    \fp_to_decimal:n { \clist_use:Nn \l_tmpa_clist { + } }
   }
   {
    \fp_if_exist:cF { g_chrisf_calc_#1_fp }
     {
      \fp_new:c { g_chrisf_calc_#1_fp }
     }
    \fp_gset:cn { g_chrisf_calc_#1_fp } { \clist_use:Nn \l_tmpa_clist { + } }
   }
 }
\DeclareExpandableDocumentCommand{\fpvar}{m}
 {
  \fp_use:c { g_chrisf_calc_#1_fp }
 }
\cs_set_eq:NN \fpeval \fp_eval:n
\ExplSyntaxOff

\begin{document}

Result: \calcsum{\one,\two,\three,\four,\five,\six,\seven,\eight,\nine,\ten}

Store: \calcsum[mysum]{\one,\two,\three,\four,\five,\six,\seven,\eight,\nine,\ten}

Compute square root: \fpeval{sqrt(\fpvar{mysum})}

\end{document}

enter image description here

On the other hand you can get away more easily:

\documentclass[a4paper,12pt]{article}
\usepackage{xparse}
\usepackage{fp}

\def\one{1}
\def\two{2}
\def\three{3}
\def\four{4}
\def\five{5}
\def\six{6}
\def\seven{}
\def\eight{8}
\def\nine{9}
\def\ten{1}

\ExplSyntaxOn
\cs_set_eq:NN \fpeval \fp_eval:n
\ExplSyntaxOff

\begin{document}

Result: \fpeval{\one+\two+\three+\four+\five+\six+\seven+\eight+\nine+\ten}

Store and compute: 
\newcommand\mysum{\one+\two+\three+\four+\five+\six+\seven+\eight+\nine+\ten}%
\fpeval{\mysum}

Compute square root: \fpeval{sqrt(\mysum)}

\end{document}

enter image description here

2
  • try with \def\ten{} (see comments under the question:-) Commented Dec 13, 2016 at 13:31
  • @DavidCarlisle I blame Bruno for that
    – egreg
    Commented Dec 13, 2016 at 16:43
4

You can't use \calcsum as defined in the question as it's not expandable: anything with an assignment has this issue. We can retain the comma list interface and make the code expandable with for example

\documentclass{article}
\usepackage{xparse}

\def\one{1}
\def\two{2}
\def\three{3}
\def\four{4}
\def\five{5}
\def\six{6}
\def\seven{}
\def\eight{8}
\def\nine{9}
\def\ten{1}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand \calcsum { m }
  {
    \fp_to_decimal:n
      { 0 \clist_map_function:nN {#1} \__calcsum:n }
  }
\cs_new:Npn \__calcsum:n #1 { + #1 }
\ExplSyntaxOff

\def\test{\calcsum{\one,\two,\three}}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand \calcroot { m }
   { \fp_to_decimal:n { sqrt(#1) } }               
\ExplSyntaxOff

\begin{document}

\calcroot{\test}

\end{document}

I would normally favour though not having separate functions for each calculation unless there is semantic meaning: this is arguable for the sum but not the root. So perhaps better is

\documentclass[a4paper,12pt]{article}
\usepackage{xparse}


\def\one{1}
\def\two{2}
\def\three{3}
\def\four{4}
\def\five{5}
\def\six{6}
\def\seven{}
\def\eight{8}
\def\nine{9}
\def\ten{1}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand \calcsum { m }
  {
    \fp_to_decimal:n
      { 0 \clist_map_function:nN {#1} \__calcsum:n }
  }
\DeclareExpandableDocumentCommand \fpeval { m }
  { \fp_to_decimal:n {#1} }
\cs_new:Npn \__calcsum:n #1 { + #1 }
\ExplSyntaxOff

\def\test{\calcsum{\one,\two,\three}}

\begin{document}

\fpeval{sqrt(\test)}

\end{document}

See egreg's answer for an approach which changes the interface a little but needs only one document command.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .