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?

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}
  • 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 5 '15 at 21:40
  • The fact that you can't use assignments inside expandable places is not from expl3 but from TeX. – Manuel Aug 5 '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 5 '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 7 '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 7 '15 at 15:45

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.