使用 latex3 循环导致“缺失数字,处理为零”

使用 latex3 循环导致“缺失数字,处理为零”

我正在尝试学习 latex3 来编写更强大的 LaTeX 函数。为此,我正在实现一个timesum包含时间(以分钟为单位)的变量。您可以将小时、天或分钟添加到该总和中。效果很好。

现在我尝试将其输出timesum分成天、小时和分钟。

但是,甚至没有找到总和中的完整天数,而是中断了Missing number, treated as zero

我不懂为什么...

\documentclass{scrlttr2}

\renewcommand\familydefault{\sfdefault}
\usepackage[defaultsans, scale=0.9]{opensans}


\ExplSyntaxOn

\fp_new:N \timesum

\NewDocumentCommand{\addtime}{O{\timesum}mm}
{
    \str_case_e:nnF { #3 } { 
        {h}{\fp_add:Nn #1 {\fp_eval:n {#2 * 60}}}
        {d}{\fp_add:Nn #1 {\fp_eval:n {#2 * 60 * 24}}}
    }
    { \fp_add:Nn #1 {#2} } % default
    #2\,#3
}

\NewDocumentCommand{\showtimesum}{O{\timesum}m}{
    \str_case_e:nnF { #2 } { 
        {h}{\fp_eval:n { #1 / 60}\,h}
        {d}{\fp_eval:n {#1 / 60 / 24}\,d}
        {min}{\fp_use:N  #1 \,min}
    }
    { \fp_use:N #1 \,min} % default
}

%\int_incr:N

\NewDocumentCommand{\strtime}{O{\timesum}}{
    \fp_new:N \l_fp_tmp_timemin             % new var
    \fp_set_eq:NN \l_fp_tmp_timemin #1      % set var to value of #1
    %\fp_use:N \l_fp_tmp_timemin                % print var
    
    % find out days iteratively
    \int_do_while:nNnn {\l_fp_tmp_timemin} {>} {1439.999} {
        \fp_sub:Nn \l_fp_tmp_timemin {1440}
        %\fp_use:N \l_fp_tmp_timemin
    }
    
}


\ExplSyntaxOff

\begin{document}
    \begin{letter}{recipient}
        \opening{opening}

        \addtime{20.5}{h}
        \addtime{30}{min}
        \addtime{2.7}{d}
        
        \showtimesum{h}
        \strtime
        
        %\showsum
        \closing{concluding text}
    \end{letter}
\end{document}

答案1

您当然可以将时间总和(以分钟为单位)存储在变量中fp,但是为了打印总时间,您需要将其四舍五入为整数。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\newtime}{m}
 {
  \fp_new:c { l_mrcarnivore_time_#1_fp }
 }
\newtime{default} % initialize one

% \addtime* will also show the added time
\NewDocumentCommand{\addtime}{sO{default}mm}
 {
  \mrcarnivore_time_add:nnn { #2 } { #3 } { #4 }
  % with \addtime* also show what's been added
  \IfBooleanT{#1}{#3\,\textup{#4}}
 }

\NewDocumentCommand{\strtime}{O{default}}
 {
  \mrcarnivore_time_str:n { #1 }
 }

\int_new:N \l__mrcarnivore_time_days_int
\int_new:N \l__mrcarnivore_time_hours_int
\int_new:N \l__mrcarnivore_time_minutes_int

\cs_new_protected:Nn \mrcarnivore_time_add:nnn
 {
  \str_case:nnF { #3 }
   {
    {h}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 * 60 } }
    {d}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 * 60 * 24 } }
    {min}{ \fp_add:cn { l_mrcarnivore_time_#1_fp } { #2 } }
   }
   {\ERROR}
 }

\cs_new_protected:Nn \mrcarnivore_time_str:n
 {
  % round to an integral number of minutes
  \int_set:Nn \l__mrcarnivore_time_minutes_int
   {
    \fp_eval:n { round( \fp_use:c { l_mrcarnivore_time_#1_fp }, 0 ) }
   }
  % compute the number of days
  \int_set:Nn \l__mrcarnivore_time_days_int
   {
    \int_div_truncate:nn { \l__mrcarnivore_time_minutes_int } { 1440 }
   }
  % remove the days
  \int_set:Nn \l__mrcarnivore_time_minutes_int
   {
    \int_mod:nn { \l__mrcarnivore_time_minutes_int } { 1440 }
   }
  % compute the number of hours
  \int_set:Nn \l__mrcarnivore_time_hours_int
   {
    \int_div_truncate:nn { \l__mrcarnivore_time_minutes_int } { 60 }
   }
  % remove the hours
  \int_set:Nn \l__mrcarnivore_time_minutes_int
   {
    \int_mod:nn { \l__mrcarnivore_time_minutes_int } { 60 }
   }
  % now print the days
  \int_compare:nT { \l__mrcarnivore_time_days_int > 0 }
   {
    \int_eval:n { \l__mrcarnivore_time_days_int }\,\textup{d}\;
   }
  % now print the hours
  \int_compare:nTF { \l__mrcarnivore_time_hours_int > 0 }
   {
    \int_eval:n { \l__mrcarnivore_time_hours_int }\,\textup{h}
   }
   {% no hours
    \unkern
   }
  \;
  % now print the minutes
  \int_compare:nTF { \l__mrcarnivore_time_minutes_int > 0 }
   {
    \int_eval:n { \l__mrcarnivore_time_minutes_int }\,\textup{min}
   }
   {% no minutes
    \unkern
   }
 }

\ExplSyntaxOff

\begin{document}

\addtime{20.5}{h}

\strtime

\addtime{30}{min}

\strtime

\addtime{2.7}{d}
        
\strtime

\end{document}

在此处输入图片描述

那怎么\unkern办呢?假设最终答案应该是“两天零八分钟”。

代码将\,在 2 和 d 之间添加一个细小的空格,并\;在其后添加一个 med 空格。如果没有小时数可显示,则此 med 空格将保留并与小时数后发出的 med 空格累积。当分钟数为零时也是如此。

相关内容