24

Is it possible to calculate the value of a finite series, say,

sum

using LaTeX 3?

4
  • 2
    Yes, but why? ;-)
    – egreg
    Commented Dec 11, 2014 at 0:27
  • 5
    @egreg I would like to create an example sheet with quite a lot of different finite sums and their values. If LaTeX 3 can handle the calculations, I can change them without forgetting to calculate their (new) values. Commented Dec 11, 2014 at 0:30
  • But you can do the above and much much more and more easily as well, using a computer algebra system, then export the results to Latex at the end.
    – Nasser
    Commented Aug 1, 2015 at 13:06
  • @Nasser That might be but the case I would like to use LaTeX for the task. I am using Mathematica 10 but that's not the point. :) egreg's solution is/was what I am/was looking for. Commented Aug 2, 2015 at 2:54

2 Answers 2

28

Yes, you can, and pretty easily too.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\computesum}{mmm}
 {% pass control to an internal function
  \svend_compute_sum:nnn { #1 } { #2 } { #3 }
 }

% a variable for storing the partial sums
\fp_new:N \l_svend_partial_sum_fp

\cs_new_protected:Npn \svend_compute_sum:nnn #1 #2 #3
 {
  % clear the variable
  \fp_zero:N \l_svend_partial_sum_fp
  % for k from #1 to #2 ...
  \int_step_inline:nnnn { #1 } { 1 } { #2 }
   {
    % ... add the current value to the partial sum so far
    \fp_add:Nn \l_svend_partial_sum_fp { #3 }
   }
  % deliver the value
  \fp_use:N \l_svend_partial_sum_fp
 }
\ExplSyntaxOff

\begin{document}
$\computesum{0}{0}{#1^2}$\par
$\computesum{0}{1}{#1^2}$\par
$\computesum{0}{2}{#1^2}$\par
$\computesum{0}{3}{#1^2}$\par
$\computesum{0}{4}{#1^2}$\par
$\computesum{0}{5}{#1^2}$\par
$\computesum{0}{6}{#1^2}$\par
$\computesum{0}{7}{#1^2}$\par
$\computesum{0}{8}{#1^2}$\par
\end{document}

Note that in the third argument #1 stands for the summation index.

In the example, #1^2 is passed as #3 to \svend_compute_sum:nnn; since the argument is used inside \int_step_inline:nnnn, where #1 stands for the current index, the magic happens. ;-)

The argument should be legal code for floating point expressions. So no hope to evaluate factorials unless you define them yourself.

enter image description here

If your summands are always integers, you can change all fp into int.

If you load also siunitx and change the internal function into

\cs_new_protected:Npn \svend_compute_sum:nnn #1 #2 #3
 {
  \fp_zero:N \l_svend_partial_sum_fp
  \int_step_inline:nnnn { #1 } { 1 } { #2 }
   {
    \fp_add:Nn \l_svend_partial_sum_fp { #3 }
   }
  \num { \fp_use:N \l_svend_partial_sum_fp }
 }

then

$\computesum{0}{300}{#1^2}$

will print like

enter image description here

7
  • 1
    @SvendTveskæg Easy enough: add \num as shown in the edit.
    – egreg
    Commented Dec 11, 2014 at 0:45
  • 1
    Would it be faster if \fp_set:Nx was used with the \int_step_function:… inside the argument (so it expands before l3fp does the computing)?
    – Manuel
    Commented Dec 11, 2014 at 2:11
  • 1
    @Manuel \int_step_inline:nnnn is not expandable. One could consider \int_step_function:nnnN, but I don't think it would be much faster.
    – egreg
    Commented Dec 11, 2014 at 9:48
  • 2
    @SvendTveskæg About the speed I don't think one can do much better. Evaluating all summands and then doing a giant \fp_eval:n doesn't seem faster at all. I'll add a few comments.
    – egreg
    Commented Dec 12, 2014 at 9:55
  • 1
    @PierPaolo The advantage is that you can use any legal expression in the third argument, where #1 stands for the current index. So $\computesum{0}{30}{2*#1}$ computes the sum of the first 30 even numbers.
    – egreg
    Commented Sep 22, 2015 at 16:22
10

You may load xintexpr for this, and allow LaTeX3 some rest.

sums

\documentclass[12pt]{article}
\usepackage[hscale=0.75]{geometry}
\usepackage{xintexpr}
\usepackage{siunitx}
\usepackage{shortvrb}

\begin{document}

$$\sum_{i=1}^{300} i^2=\num{\xinttheexpr add(i^2, i=1..300)\relax }$$

% For some reason, this doesn't go through:
% \num{\xintthefloatexpr [14] add(1/i^2,i=1..50)\relax}
% one needs to first expand the \num argument:
% \expandafter\num\expandafter
%     {\romannumeral-`0\xintthefloatexpr [14] add(1/i^2,i=1..50)\relax}
%

The float version does each addition with 16 digits floats, hence the last
digit may be a bit off.

$$\sum_{i=1}^{50} \frac1{i^2}=
  \xintFrac{\xinttheexpr reduce(add(1/i^2,i=1..50))\relax}
  \approx  \xintthefloatexpr add(1/i^2,i=1..50)\relax$$

If one has anyhow computed an exact value, it is better to deduce the
float from it rather than evaluating the sum as a sum of floats.

\noindent\verb|\oodef\MySum {\xinttheexpr reduce(-add((-1)^i/i^2,i=1..50))\relax }|

\oodef\MySum {\xinttheexpr reduce(-add((-1)^i/i^2,i=1..50))\relax }

$$\sum_{i=1}^{50} \frac{(-1)^{i-1}}{i^2}=
\xintFrac{\MySum}$$
\verb|$$\xintDigits:=48; \approx\xintthefloatexpr \MySum\relax$$|
$$\xintDigits:=48; \approx\xintthefloatexpr \MySum\relax$$

\end{document}
2
  • Really nice, jfbu. Thank you for the contribution! Commented Dec 13, 2014 at 3:47
  • 1
    However, if you need sin, cos, exp, log they are not implemented yet in xintexpr, only sqrt is. The \xintthefloatexpr\MySum\relax thing is a bit inefficient as it will first expand \MySum then parse its (longish) numerator and denominator digit by digit. Better is \xintFloat [48]{\MySum} or the slightly prettier \xintPFloat [48]{\MySum} (due to oversight, this \xintPFloat is not documented a.t.t.o.w in xint.pdf). Both can serve as arguments to siunitx's \num macro. For computations with only integers you can use \xinttheiiexpr ...\relax. / = rounded division
    – user4686
    Commented Dec 13, 2014 at 8:23

You must log in to answer this question.

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