2

I'n trying to combine the code from the answers "Sum of finite series using LaTeX 3" and "Reducing fraction using LaTeX 3" to automatically calculate a finite sum as either the numerator or denominator (in this case the numerator) in a fraction and then automatically reduce this fraction.

Here is what I have tried so far:

\documentclass{article}

\usepackage{siunitx}

\ExplSyntaxOn

% calculations
\cs_new_eq:NN \calc \fp_eval:n

% finite sum
\NewDocumentCommand{\computesum}{mmm}{
  \compute_sum:nnn{#1}{#2}{#3}
}

\fp_new:N \l_partial_sum_fp

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

% reduce fraction
\cs_new:Nn \gcd:nn{
  \int_compare:nNnTF{#2} = {0}{#1}
    {\gcd:ff{#2}{\int_mod:nn{#1}{#2}}}
}
\cs_generate_variant:Nn \gcd:nn{ff}

\int_new:N \l__tmp_int
\cs_new:Nn \reduced:nn{
  \int_set:Nn \l__tmp_int{\gcd:nn{#1}{#2}}
  \frac{\reduced_wrap:n{\int_eval:n{#1/\l__tmp_int}}}%
       {\reduced_wrap:n{\int_eval:n{#2/\l__tmp_int}}}
}
\cs_set_eq:NN \reduced_wrap:n \relax

\NewDocumentCommand\ReducedFractionWrapper{m}
  {\cs_set_eq:NN \reduced_wrap:n#1}
\NewDocumentCommand\ReducedFraction{o>{\SplitList{/}}m}{
  \group_begin:
    \IfValueT{#1}{\reducedFractionWrapper{#1}}
    \int_compare:nTF
      {\tl_count:n{#2} = 2}
      {\reduced:nn#2}
      {}
  \group_end:
}

\ExplSyntaxOff


\begin{document}

\def\maksimum{20}
\def\produkt{25}
\ReducedFractionWrapper{\num}

\[
  \ReducedFraction{\computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}/\calc{(\maksimum+1)^2}}
%  = \frac{117}{441}
%  = \frac{13}{49}
\]

\end{document}

This gives the following error message:

! Missing number, treated as zero.
<to be read again> 
                   \tex_let:D 
l.62 .../#1),\maksimum)+2}/\calc{(\maksimum+1)^2}}

I think that the error is do to the #1 but I don't know how to fix it.

How do I change the code in order to make it do what I want?

1 Answers1

3

You can't have assignments there, which \computesum has. A basic option is to \computesum before, and then \usesum in the calculation.

\NewDocumentCommand \computesum { m m m }
 { \svend_compute_sum:Nnnn \l_svend_partial_sum_fp { #1 } { #2 } { #3 } }
\NewDocumentCommand \usesum { }
 { \svend_use_sum:N \l_svend_partial_sum_fp }

\fp_new:N \l_svend_partial_sum_fp
\cs_new_protected:Nn \svend_compute_sum:Nnnn
 {
  \fp_zero:N #1
  \int_step_inline:nnnn { #2 } { 1 } { #3 } { \fp_add:Nn #1 { #4 } }
 }
\cs_new:Npn \svend_use_sum:N { \fp_use:N }

...

\[
  \computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}
  \ReducedFraction
   {\usesum/\calc{(\maksimum+1)^2}}
%  = \frac{117}{441}
%  = \frac{13}{49}
\]

By the way, you have a little mix of things, like \num inside \svend_compute_sum:Nnnn, why? I think you should clear the code a little bit. For instance, you use \int_compare:nNnTF while :nNnT would be enough).

And also, follow the indenting rules of expl3, which, in my opinion, help readability a lot.


Here's a first round trying to format and use better names (beware, I'm neither Enrico nor Joseph).

\documentclass{scrartcl}

\usepackage{xparse,siunitx}

\ExplSyntaxOn

\cs_set_eq:NN \calc \fp_eval:n

\NewDocumentCommand \computesum { m m m }
 { \svend_compute_sum:Nnnn \l_svend_partial_sum_fp { #1 } { #2 } { #3 } }
\DeclareExpandableDocumentCommand \usesum { }
 { \svend_use_sum:N \l_svend_partial_sum_fp }

\fp_new:N \l_svend_partial_sum_fp
\cs_new_protected:Nn \svend_compute_sum:Nnnn
 {
  \fp_zero:N #1
  \int_step_inline:nnnn { #2 } { 1 } { #3 } { \fp_add:Nn #1 { #4 } }
 }
\cs_new:Npn \svend_use_sum:N { \fp_use:N }

\cs_new:Nn \svend_gcd:nn
 {
  \int_compare:nNnTF { #2 } = { 0 } { #1 }
    { \svend_gcd:ff { #2 } { \int_mod:nn { #1 } { #2 } } }
 }
\cs_generate_variant:Nn \svend_gcd:nn { ff }

\int_new:N \l_svend_tmp_int
\cs_new:Nn \svend_reduced:nn
 {
  \int_set:Nn \l_svend_tmp_int { \svend_gcd:nn { #1 } { #2 } }
  \frac{ \svend_reduced_wrap:n { \int_eval:n { #1/\l_svend_tmp_int } } }
       { \svend_reduced_wrap:n { \int_eval:n { #2/\l_svend_tmp_int } } }
 }
\cs_set_eq:NN \svend_reduced_wrap:n \use:n

\NewDocumentCommand \ReducedFractionWrapper { m }
 { \cs_set_eq:NN \svend_reduced_wrap:n #1 }
\NewDocumentCommand \ReducedFraction { o >{\SplitList{/}} m }
 {
  \group_begin:
  \IfValueT{#1}{\reducedFractionWrapper{#1}}
  \int_compare:nNnT { \tl_count:n { #2 } } = { 2 }
    { \svend_reduced:nn #2 }
  \group_end:
 }

\ExplSyntaxOff


\begin{document}

\def\maksimum{20}
\def\produkt{25}
\ReducedFractionWrapper\num

\[
  \computesum{1}{\maksimum}{min(floor(\produkt/#1),\maksimum)+2}
  \ReducedFraction
   {\usesum/\calc{(\maksimum+1)^2}}
%  = \frac{117}{441}
%  = \frac{13}{49}
\]

\end{document}
Manuel
  • 27,118
  • Very nice! I'm not familiar with LaTeX 3 syntax yet so if I can make you clean up my code, I will very much appreciate it. :) – Svend Tveskæg Aug 05 '15 at 21:40
  • The fact that you can't use assignments inside expandable places is not from expl3 but from TeX. – Manuel Aug 05 '15 at 21:53
  • 1
    Okey. It's similar to \pgfmathparse{..}\pgfmathresult, you can't use \pgfmathparse in expandable contexts. And yes, anyone is welcome to edit this answer. I don't like this solution, and I would look probably for another solution so that I don't need to precalculate the sum. For instance checking if \computesum is inside the argument, and, in that case, replace it with its value, but it's a little bit dirty, and this code is clearer, in my opinion. – Manuel Aug 05 '15 at 21:58
  • There is no need to load niether expl3 nor xparse so I have removed them from your MWE; I hope it is okay. – Svend Tveskæg Aug 07 '15 at 15:08
  • I prefer to have the packages explicitly called (may be expl3 is too much, but xparse and siunitx I think it's useful to have both), but the result is exactly the same, so I have no problem with your edit. – Manuel Aug 07 '15 at 15:45
  • Okay. I'll add xparse again, then. :) – Svend Tveskæg Aug 07 '15 at 17:08
  • Any further code improvements? You wrote about a first round. :) – Svend Tveskæg Aug 24 '15 at 15:51
  • @SvendTveskæg I'm not sure what you mean. (Sorry for the delay, I forgot.) – Manuel Sep 04 '15 at 12:22