Is it possible to calculate the value of a finite series, say,
using LaTeX 3?
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.
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
\fp_set:Nx
was used with the \int_step_function:…
inside the argument (so it expands before l3fp
does the computing)?
\int_step_inline:nnnn
is not expandable. One could consider \int_step_function:nnnN
, but I don't think it would be much faster.
\fp_eval:n
doesn't seem faster at all. I'll add a few comments.
#1
stands for the current index. So $\computesum{0}{30}{2*#1}$
computes the sum of the first 30 even numbers.
You may load xintexpr for this, and allow LaTeX3
some rest.
\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}
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
:)
egreg's solution is/was what I am/was looking for.