23

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

sum

using LaTeX 3?

  • 2
    Yes, but why? ;-) – egreg Dec 11 '14 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. – Svend Tveskæg Dec 11 '14 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 Aug 1 '15 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. – Svend Tveskæg Aug 2 '15 at 2:54
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

  • 1
    @SvendTveskæg Easy enough: add \num as shown in the edit. – egreg Dec 11 '14 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 Dec 11 '14 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 Dec 11 '14 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 Dec 12 '14 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 Sep 22 '15 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}
  • Really nice, jfbu. Thank you for the contribution! – Svend Tveskæg Dec 13 '14 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 Dec 13 '14 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.