Round command argument before using

One approach would be this. ceil and floor are alternatives to round. There are also command versions of each, as Alan Munn mentions in a comment, i.e. \pgfmathround{#1}, \pgfmathceil{#1}, \pgfmathfloor{#1}.

\documentclass{article}
\usepackage{pgffor}
\newcommand{\myrepeat}[2]{%
   \pgfmathparse{round(#1)}% set rounding function here
   \foreach \n in {1,...,\pgfmathresult}{#2}}

\begin{document}
\myrepeat{3.2}{x}  % should print xxx

\myrepeat{3.7}{x}  % should print xxxx
\end{document}

Here's a fairly general macro where you can set the mode as an optional argument: choose between round (default), floor, ceil or nearest.

The \generalrepeat macro accepts the starting point (an integer), the step (an integer, default 1) and the end point (a floating point number).

The \myrepeat macro is a reduced version, always starting from 1 with step 1.

In the final argument (code to repeat), the current value in the loop is denoted by #1.

\documentclass{article}
\usepackage{xfp}

\ExplSyntaxOn
\NewDocumentCommand{\generalrepeat}
 {
  O{round} % the mode
  m % the starting point
  O{1} % the step
  m % the final point
  +m % the code to repeat (can contain \par)
 }
 {
  \klinke_repeat_general:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 }
 }

\NewDocumentCommand{\myrepeat}
 {
  O{round} % the mode
  m % the final point
  +m % the code to repeat (can contain \par)
 }
 {
  \klinke_repeat_general:nnnnn { #1 } { 1 } { 1 } { #2 } { #3 }
 }

\cs_new_protected:Nn \klinke_repeat_general:nnnnn
 {
  \cs_set_eq:Nc \__klinke_repeat_mode:n { __klinke_repeat_#1:n }
  \cs_set_protected:Nn \__klinke_repeat_code:n { #5 }
  \int_step_function:nnnN
   { #2 } % start
   { #3 } % step
   { \__klinke_repeat_mode:n { #4 } } % end
   \__klinke_repeat_code:n % action
 }

\cs_new:Nn \__klinke_repeat_round:n { \fp_eval:n { round(#1,0,1) } }
\cs_new:Nn \__klinke_repeat_floor:n { \fp_eval:n { floor(#1,0) } }
\cs_new:Nn \__klinke_repeat_ceil:n  { \fp_eval:n { ceil(#1,0) } }
\cs_new:Nn \__klinke_repeat_nearest:n
 {
  \fp_eval:n { #1 - floor(#1,0) < 0.5 ? floor(#1,0) : ceil(#1,0) }
 }
\ExplSyntaxOff

\begin{document}

\generalrepeat{1}{3.4}{#1 }---
\generalrepeat{1}{3.5}{#1 }---
\generalrepeat{1}{3.6}{#1 }

\generalrepeat[ceil]{1}{3.4}{#1 }---
\generalrepeat[ceil]{1}{3.5}{#1 }---
\generalrepeat[ceil]{1}{3.6}{#1 }

\generalrepeat[floor]{1}{3.4}{#1 }---
\generalrepeat[floor]{1}{3.5}{#1 }---
\generalrepeat[floor]{1}{3.6}{#1 }

\generalrepeat[nearest]{1}{3.4}{#1 }---
\generalrepeat[nearest]{1}{3.5}{#1 }---
\generalrepeat[nearest]{1}{3.6}{#1 }

\myrepeat{3.4}{x}---\myrepeat[floor]{3.4}{x}---%
\myrepeat[ceil]{3.4}{x}---\myrepeat[nearest]{3.4}{x}

\myrepeat{3.5}{x}---\myrepeat[floor]{3.5}{x}---%
\myrepeat[ceil]{3.5}{x}---\myrepeat[nearest]{3.5}{x}

\myrepeat{3.6}{x}---\myrepeat[floor]{3.6}{x}---%
\myrepeat[ceil]{3.6}{x}---\myrepeat[nearest]{3.6}{x}

\end{document}

enter image description here

Both round and nearest integer are implemented to go upward in case of a tie (the 3.5 case).


You can use the expandable functionality of xfp:

enter image description here

\documentclass{article}

\usepackage{pgffor,xfp}

\newcommand{\myrepeat}[2]{\foreach \n in {1,...,\fpeval{floor(#1)}}{#2}}

\begin{document}

\myrepeat{6}{x}                % prints xxxxxx

\myrepeat{3.2}{x}              % prints xxx

\myrepeat{8.1 * sin(pi / 6)}{x}% prints xxxx sin(pi/6) = 1/2; 8.1 * 1/2 = 4.05

\end{document}

You can use ceiling(#1), or round(#1,0), or whatever calculation you want.

Tags:

Macros