TransWikia.com

Why is there an arithmetic overflow in the progress bar with more than 44 frames?

TeX - LaTeX Asked on February 20, 2021

I am trying to implement a progress bar into my beamer theme, but as soon as I hit 45 frames, I get the error message

! Arithmetic overflow.
progressbar@progressbar ...progressbar@tmpcounta 
divide progressbar@tmpdi...

Here is my MWE:

documentclass{beamer}

usepackage{tikz}

makeatletter
defprogressbar@progressbar{} % the progress bar
newcountprogressbar@tmpcounta% auxiliary counter
newcountprogressbar@tmpcountb% auxiliary counter
newdimenprogressbar@pbht %progressbar height
newdimenprogressbar@pbwd %progressbar width
newdimenprogressbar@tmpdim % auxiliary dimension

progressbar@pbwd=paperwidth
progressbar@pbht=1cm

% the progress bar
defprogressbar@progressbar{%
    
    progressbar@tmpcounta=insertframenumber
    progressbar@tmpcountb=inserttotalframenumber
    progressbar@tmpdim=progressbar@pbwd
    multiplyprogressbar@tmpdim by progressbar@tmpcounta
    divideprogressbar@tmpdim by progressbar@tmpcountb
    
    begin{tikzpicture}
    useasboundingbox (0pt, 0pt) rectangle ++ (progressbar@pbwd, progressbar@pbht);
    begin{scope}
    clip (progressbar@tmpdim, 0pt) rectangle (progressbar@pbwd, progressbar@pbht);
    node[anchor=south west,inner sep=0pt,outer sep=0pt,minimum height=1cm,minimum width=paperwidth,fill=green] at (0pt,0pt) {};
    end{scope}
    end{tikzpicture}%
}

addtobeamertemplate{footline}{}{vspace*{-1cm}progressbar@progressbar}
makeatother

begin{document}
foreach x in {1,2,...,45} {begin{frame}[label=test]{My frame}
    Test x
end{frame}}

end{document}

What is the reason behind and how can I avoid it?

2 Answers

TeX has a maxdimen (16383.99999pt), which represents the largest dimension you can use in an dimension expression. See discussions among maxdimen on this site, including my answer.

When x == 45,

  • progressbar@tmpdim == 364.19536pt and progressbar@tmpcounta == 45,
  • their multiplication 364.19536pt * 45 = 16,388.7912pt, is slightly larger than maxdimen, hence raises "arithmetic overflow" and the result of multiplication is truncated.

Since the final result @tmpdim * @tmpcounta / @tmpcountb is smaller than maxdimen, we can firstly compute @tmpcounta / @tmpcountb, then compute @tmpdim * <ratio>. Here is a try making use of pgfmathparse from pgfmath, which is an autoloaded sub-package of tikz:

documentclass{beamer}

usepackage{tikz}

makeatletter
defprogressbar@progressbar{} % the progress bar
newcountprogressbar@tmpcounta% auxiliary counter
newcountprogressbar@tmpcountb% auxiliary counter
newdimenprogressbar@pbht %progressbar height
newdimenprogressbar@pbwd %progressbar width
newdimenprogressbar@tmpdim % auxiliary dimension

progressbar@pbwd=paperwidth
progressbar@pbht=1cm

% the progress bar
defprogressbar@progressbar{%
    progressbar@tmpcounta=insertframenumber
    progressbar@tmpcountb=inserttotalframenumber
    progressbar@tmpdim=progressbar@pbwd
    % to show current values
    rlap{theprogressbar@tmpdim, theprogressbar@tmpcounta}%
    pgfmathparse{progressbar@tmpcounta/progressbar@tmpcountb}%
    progressbar@tmpdim=pgfmathresultprogressbar@tmpdim
    begin{tikzpicture}
    useasboundingbox (0pt, 0pt) rectangle ++ (progressbar@pbwd, progressbar@pbht);
    begin{scope}
      clip (progressbar@tmpdim, 0pt) rectangle (progressbar@pbwd, progressbar@pbht);
      node[anchor=south west,inner sep=0pt,outer sep=0pt,minimum height=1cm,minimum width=paperwidth,fill=green] at (0pt,0pt) {};
    end{scope}
    end{tikzpicture}%
}

addtobeamertemplate{footline}{}{vspace*{-1cm}progressbar@progressbar}
makeatother

begin{document}
foreach x in {1,2,...,45} {begin{frame}[label=test]{My frame}
    Test x
end{frame}}

end{document}

Update

Sorry, I paid too much attention to the error message "arithmetic overflow" yesterday, but not the whole picture of drawing a progress bar. Inspired by @TobiBS's answer, I find the implementation can be further simplified to

documentclass{beamer}
usepackage{tikz}

makeatletter
newdimenprogressbar@height
progressbar@height=1cm

addtobeamertemplate{footline}{}{%
  begin{tikzpicture}
    useasboundingbox (0pt, 0pt) rectangle (paperwidth, progressbar@height);
    % you can use pgfmath expressions directly in coordinate specifications
    fill[green] (insertframenumber/inserttotalframenumber*paperwidth, 0)
       rectangle (paperwidth, progressbar@height);
  end{tikzpicture}%
}
makeatother

begin{document}
foreach x in {1,2,...,50} {
  begin{frame}{My frame}
    Test x
  end{frame}
}
end{document}

Correct answer by muzimuzhi Z on February 20, 2021

A more simplified approach that I am now using might be a bit easier to read, but of course not as flexible as before, but it makes use of the fact that for PGF you don't need to convert the macros to counters before, hence this works to produce a progress bar that is variable in height and is inverted. It also takes into account muzimuzhi's comment regarding the use of pgfmathsetmacro:

documentclass{beamer}

usepackage{tikz}

makeatletter
newdimenprogressbar@height
newcountprogressbar@progress
progressbar@height=1cm

addtobeamertemplate{footline}{}{%
begin{tikzpicture}
useasboundingbox (0pt, 0pt) rectangle ++ (paperwidth, progressbar@height);
begin{scope}
pgfmathsetmacroprogressbar@progress{insertframenumber/inserttotalframenumber}
clip (progressbar@progress * paperwidth, 0pt) rectangle (paperwidth, progressbar@height);
node[anchor=south west,inner sep=0pt,outer sep=0pt,minimum height=1cm,minimum width=paperwidth,fill=green] at (0pt,0pt) {};
end{scope}
end{tikzpicture}%
}
makeatother

begin{document}
    foreach x in {1,2,...,50} {begin{frame}{My frame}
        Test x
end{frame}}

end{document}

Answered by TobiBS on February 20, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP