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
16
  • @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, 2018 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, 2018 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, 2018 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, 2018 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, 2018 at 23:50

3 Answers 3

7

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.

10
  • With etex: \def\divreg#1#2{#1=\dimexpr#1/#2\relax}. Or just: \def\divreg#1#2{\divide #1by#2}
    – Skillmon
    Mar 18, 2018 at 15:08
  • @Skillmon This does not work when #2 is decimal number, for example 1.5
    – wipet
    Mar 18, 2018 at 16:07
  • Yes, that's correct.
    – Skillmon
    Mar 18, 2018 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, 2018 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, 2018 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .