4

I know in latex it is possible to use counters which are based on integers. Is there also some way to define a floating point register to perform simple arithmetic operations?

Basically I would need some way to write something like

\newreg{myx}
\setreg{myx}{0.0}
\addreg{myx}{0.5}
\addreg{myx}{-0.25}
\valuereg{myx} % this expands to 0.25
  • @Werner It seems that it is not quite duplicate because OP needs something more simple than full float point arithmetic. This can be simply done by \newdimen\myx. Because this question is marked as "duplicate", I am unable to show full answer here. Unfortunately. – wipet Mar 14 '18 at 15:48
  • @wipet: There's no mention of the level of detail required, and it's all covered in the linked question. You can, of course, vote to re-open here since you have that privilege. Perhaps you can add your TeX answer to the linked duplicate...? – Werner Mar 14 '18 at 16:05
  • The linked answer seems indeed to propose solutions more complicated as necessary. I solved using the idea suggested by wipet. That is a combination of \newdimen (to init) \advance (to sum) and \the (to visualize) plus the aid of the latex macro \strip@pt (to strip the unit). – nicmus Mar 14 '18 at 16:33
  • @werner I cannot add my answer to the linked duplicate because there is question how to calculate 100*round((V-F)/T,2), where V, F and T are variables. This is much more complicated, this cannot be simply done using \newdimen. So, your decision about "duplicate question" yields to missing answer here. But OP understood my idea, fortunately. – wipet Mar 14 '18 at 20:08
  • 1
    @nicmus: Here's an easy implementation for what you're after - code. No testing for existing "variables" or "registers" is implemented, but it is extendable to use calculations in the assignment. – Werner Mar 15 '18 at 23:50
6

If you need only addition, subtraction and multiplication and numbers are expected in the range +-16380 with four (or less) digits after decimal point then you can use directly dimension registers supported naturally by TeX. For example:

\def\newreg{\csname newdimen\endcsname}
\def\setreg#1#2{#1=#2pt }
\def\addreg#1#2{\advance#1by#2pt }
\def\mulreg#1#2{#1=#2#1}
\def\valuereg#1{\expandafter\ignorept\the#1}
\bgroup\lccode`\?=`\p \lccode`\!=`\t \lowercase{\egroup\def\ignorept#1?!{#1}}

\newreg\myx
\setreg\myx {0.0}
\addreg\myx {0.5}
\addreg\myx {-0.25}
\valuereg\myx  % this expands to 0.25

\bye

But division using dimension registers is somewhat more complicated.

Of course, you can use pgfmath or calc or lua or expl3 or apnum or somewhat similar but with declared needs it seems like using cannon on a sparrow.

  • With etex: \def\divreg#1#2{#1=\dimexpr#1/#2\relax}. Or just: \def\divreg#1#2{\divide #1by#2} – Skillmon Mar 18 '18 at 15:08
  • @Skillmon This does not work when #2 is decimal number, for example 1.5 – wipet Mar 18 '18 at 16:07
  • Yes, that's correct. – Skillmon Mar 18 '18 at 16:16
  • one more doubt... I have defined: {\catcode``p=12 \catcode``t=12 \global\def\removedim#1pt{#1}} and seems to work. Would your definition \ignorept be safer? P.S. I used double backticks because of stack exchange code syntax. – nicmus Mar 22 '18 at 10:18
  • @nicmus If you are using LaTeX then you can use some similar macro from LaTeX. My macros (as usual) are LaTeX independent, so I need to define \ignorept specially. – wipet Mar 22 '18 at 18:02
6

Here a simple example with pgfmath, part of pgf/TikZ:

\documentclass{article}
\usepackage{pgfmath}
\begin{document}
  \pgfmathsetmacro\myx{0}
  \pgfmathsetmacro\myx{\myx + 0.5}
  \pgfmathsetmacro\myx{\myx - 0.25}
  \myx
\end{document}

Result

The "register" is a simple macro (\myx) here. Also, an "addto" macro can be defined:

\documentclass{article}
\usepackage{pgfmath}

% #1: macro token, e.g. \myx
% #2: math expression
\newcommand*{\pgfmathaddtomacro}[2]{%
  \pgfmathsetmacro#1{#1+(#2)}
}

\begin{document}
  \pgfmathsetmacro\myx{0}
  \pgfmathaddtomacro\myx{0.5}
  \pgfmathaddtomacro\myx{-0.25}
  \myx
\end{document}
5

You can use the powerful floating point module of expl3. I use global assignments, like for LaTeX counters, but it would be possible to do local assignments.

\documentclass{article}
\usepackage{xparse,xfp}

\ExplSyntaxOn
\NewDocumentCommand{\newreg}{m}
 {
  \fp_new:c { g_nicmus_#1_fp }
 }
\NewDocumentCommand{\setreg}{mm}
 {
  \fp_gset:cn { g_nicmus_#1_fp } { #2 }
 }
\NewDocumentCommand{\addreg}{mm}
 {
  \fp_gset:cn { g_nicmus_#1_fp } { \fp_use:c { g_nicmus_#1_fp } + (#2) }
 }
\NewExpandableDocumentCommand{\valuereg}{m}
 {
  \fp_use:c { g_nicmus_#1_fp }
 }
\ExplSyntaxOff

\newreg{myx}

\begin{document}

\setreg{myx}{0.0}
\addreg{myx}{0.5}
\addreg{myx}{-0.25}
\valuereg{myx} % this expands to 0.25

\addreg{myx}{sqrt(3)+pi}

\valuereg{myx} % this expands to 5.12364346115867

\fpeval{round(\valuereg{myx},2)} % this expands to 5.12

\end{document}

enter image description here

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.